lOMoARcPSD|59149108
BUỔI 3: ARRAYLIST, LIST, BINDINGLIST
1. Collection và Generic
1.1. Collection
Collection là một tập hợp các dữ liệu không cùng kiểu.
− Ưu điểm: khả năng tương tác và thay đổi dữ liệu bên trong ngay tại thời điểm chạy
(runtime).
− Thuộc thư viện System.Collections
− Các lớp Collection được sử dụng cho nhiều mục đích khác nhau như cấp phát bộ nhớ
động cho các phần tử, hay truy cập một danh sách các item dựa trên chỉ mục, …
− Các Collection phổ biến: ArrayList, Hashtable, DictionaryEntry,
SortedList, Stack, Queue, BitArray
1.2. Generic
− Được giới thiệu từ C# 2.0. Generic cho phép xác định một class với trình giữ chỗ
(placeholders) cho fields, methods, parameters, …
− Generic thay thế các placeholders này bằng một số loại dữ liệu cụ thể tại thời gian
biên dịch (compile time).
Generic được định nghĩa bằng cách sử dụng dấu ngoặc nhọn <>
− Đặc điểm của generic:
+ Giúp tối đa hóa sử dụng lại code (chỉ cần viết 1 hàm có thể tái sử dụng cho nhiều
kiểu dữ liệu), an toàn và tăng tốc độ.
+ Có thể dùng generic với: interfaces, classes, methods, events, delegates, structs. + Có
thể dùng generic với: interfaces, classes, methods, events, delegates, structs.
+ Có thể lấy thông tin của kiểu dữ liệu được sử dụng bởi generic ở thời điểm runtime
bằng Reflection.
− Các Generic collections được sử dụng phổ biến: List<T>,
Dictionary<TKey,
TValue>, Hashset<T>, SortedList<Tkey, TValue>, Stack<T>,
Queue<T>
2. ArrayList
− Là một collection (không phải generic) − Kích thước tăng tự động
− Có thể được sử dụng để thêm dữ liệu chưa biết kiểu và kích thước − Tạo một
ArrayList
lOMoARcPSD|59149108
using System.Collections;
ArrayList arList = new ArrayList(); // hoc var
arList = new ArrayList();
− Thêm phần tử vào ArrayList
using System.Collections;
ArrayList arList = new ArrayList();
arList.Add(1); arList.Add(“Hello”);
arList.Add(true); arList.Add(4.5);
arList.Add(null);
Hoặc
using System.Collections;
ArrayList arList = new ArrayList(){ 2, “Hello”, “ ”, true, 4.5,
null};
− Truy cập vào ArrayList:
+ Thực thi giao diện IList
+ Sử dụng index, tương tự mảng thông thường + Ép kiểu loại phù hợp hoặc sử dụng
biến var
var arlist = new ArrayList() {1, "Bill", 300, 4.5f };
int firstElement = (int) arlist[0]; //returns
1
string secondElement = (string) arlist[1]; //returns
"Bill"
//int secondElement = (int) arlist[1]; //Error: cannot cover string
to int var firstElement = arlist[0]; //returns 1 var secondElement =
arlist[1]; //returns "Bill"
//var fifthElement = arlist[5]; //Error: Index out of range arlist[0]
= "Steve"; arlist[1] = 100;
//arlist[5] = 500; //Error: Index out of range
− Duyệt ArrayList
lOMoARcPSD|59149108
ArrayList arlist = new ArrayList() {1, "Bill", 300, 4.5F}; foreach
(var item in arlist)
Console.Write(item + ", "); //output: 1, Bill, 300, 4.5,
− Thêm phần tử vào ArrayList
+ Cấu trúc: void Insert(int index, Object value)
ArrayList arlist = new ArrayList() {1, "Bill", 300,
4.5F}; arlist.Insert(1, "Second Item"); foreach (var val
in arlist)
Console.WriteLine(val);
+ Thêm một collection: InsertRange()
− Xóa phần tử: Remove(), RemoveAt(), RemoveRange
ArrayList arlist = new ArrayList() {1, null, "Bill", 300, 4.5F, “ ”,
300 }; arlist.Remove(null); //xóa phn t null đu tiên
arlist.RemoveAt(4); //xóa phn t ti index 4
arlist.RemoveRange(0, 2); //Xóa 02 phn t bt đu t index 0
− Kiểm tra phần tử trong ArrayList
ArrayList arlist = new ArrayList() {1, null, "Bill", 300, 4.5F,
“ ”, 300 };
Console.WriteLine(arList.Contains(300)); // true
Console.WriteLine(arList.Contains(10)); // false
− Các thuộc tính của ArrayList: Capacity, Count, IsFixedSize,
IsReadOnly, Item
− Các phương thức: Add()/AddRange(), Insert()/InsertRange(),
Remove()/RemoveRange(), RemoveAt(), Sort(), Reverse(),
Contains(), Clear(), CopyTo(), GetRange(), IndexOf(), ToArray()
3. List<T>
− Tập hợp các đối tượng có thể được truy cập bằng chỉ mục và có các phương pháp sắp
xếp, tìm kiếm và sử đổi.
− Phiên bản generic của ArrayList, thuộc không gian System.Collections.Generic −
Tạo một List
lOMoARcPSD|59149108
List<int> primeNumbers = new List<int>(); primeNumbers.Add(1);
primeNumbers.Add(3); primeNumbers.Add(5); primeNumbers.Add(7);
var cities = new List<string>(); cities.Add("New York");
cities.Add("London"); cities.Add("Mumbai");
cities.Add("Chicago"); cities.Add(null);
var bigCities = new List<string>(){"New York", "London", "Mumbai",
"Chicago"};
var students = new List<Student>() { new
Student(){ Id = 1, Name="Bill"}, new
Student(){ Id = 2, Name="Steve"}, new
Student(){ Id = 3, Name="Ram"}, new
Student(){ Id = 4, Name="Abdul"}
};
− Thêm một Array vào List: void AddRange(IEnumerable<T> collection)
string[] cities = new string[3]{ "Mumbai", "London", "New York" };
var popularCities = new List<string>();
popularCities.AddRange(cities); var favouriteCities
= new List<string>();
favouriteCities.AddRange(popularCities);
− Truy cập vào một List
List<int> numbers = new List<int>() { 1, 2, 5, 7, 8, 10 };
Console.WriteLine(numbers[0]); // prints 1
Console.WriteLine(numbers[1]); // prints 2
Console.WriteLine(numbers[2]); // prints 5
Console.WriteLine(numbers[3]); // prints 7
for(int i = 0; i < numbers.Count; i++)
Console.WriteLine(numbers[i]);
− Chèn phần tử
lOMoARcPSD|59149108
var numbers = new List<int>(){ 10, 20, 30, 40 };
numbers.Insert(1, 11);// chèn 11 vào index 1: sau 10 foreach
(var num in numbers)
Console.Write(num);
− Xóa phần tử
var numbers = new List<int>(){ 10, 20, 30, 40,
10 }; numbers.Remove(10); numbers.RemoveAt(2);
//numbers.RemoveAt(10); //throws ArgumentOutOfRangeException foreach
(var el in intList)
Console.Write(el);
− Kiểm tra phần tử
var numbers = new List<int>(){ 10, 20, 30, 40 };
numbers.Contains(10); // returns true numbers.Contains(11);
// returns false numbers.Contains(20); // returns true
4. Yêu cầu thực hành
a) Thực hiện các ví dụ phần 2 và 3 trong C# (Console)
b) Viết chương trình cho phép người dùng nhập vào các số nguyên (không giới hạn lần
nhập) với câu lệnh sau:
sum: hiển thị tổng các số đã nhập đến hiện tại
view: hiển thị tất cả các số đã nhập end: thoát
- Hiển thị menu gồm 4 tùy chọn: append, sum, view, end với
+ append: nhập vào số nguyên và thêm vào danh sách
+ sum: hiển thị tổng số có trong danh sách
+ view: hiển thị danh sách số nguyên
+ end: kết thúc chương trình
lOMoARcPSD|59149108
c) Viết một struct Point3D biểu diễn một điểm trong không gian 3D với tọa độ x, y, z.
Viết một chương trình với menu cho phép người dùng thêm 1 điểm, hiển thị tất cả các
điểm và thoát chương trình.
struct Point3D
{
public int x; public int y; public int z;
}
d) Mở rộng câu b với các câu lệnh:
del xx: xóa phần tử tại vị trí xx insert a b:
chèn phần tử có giá trị b vào vị trí a
lOMoARcPSD|59149108
5. BindingList
Được sử dụng làm lớp sở để tạo chế liên kết dữ liệu hai chiều; thường được sử
dụng trong gắn kết dữ liệu (data binding) trong Windows Forms để cung cấp nguồn dữ
liệu động cho các điều khiển như DataGridView, ListBox, ComboBox Yêu cầu thực
hiện:
Tạo một form hiển thị danh sách các chuỗi được nhập từ bàn phím
Control
Name
Properties
Form
frmMain
Name: frmMain
Text: Minh họa Binding List
Textbox (trái)
txtInput
Name: txtInput
Tabindex: 0
Textbox (phải)
txtIndex
Name: txtIndex
Tabindex: 1
lOMoARcPSD|59149108
Button
btnAdd
Name: btnAdd
Control
Name
Properties
Text: Thêm
Tabindex: 2
Button
btnRemove
Name: btnRemove
Text: Xóa
Tabindex: 3
Button
btnUpdate
Name: btnUpdate
Text: Sửa
Tabindex: 4
ListBox
lstbList
Name: lstbList
Tabindex: 5
Trong class frmMain khai báo một đối tượng BindingList
private BindingList<string> str_list;
Đối tượng được khởi tạo trong hàm khởi tạo
public frmMain()
{
InitializeComponent();
str_list= new BindingList<string>();
}
Khi sự kiện load của form được gọi, chỉ định nguồn dữ liệu của listbox là
BindingList đã tạo
lstbList.DataSource = str_list;
Sự kiện click của nút btnAdd: khi người dùng chọn Thêm dữ liệu được nhập
trong ô txtInput sẽ được thêm vào str_list và hiển thị trong listbox
+ Nếu người dùng nhập index không là số nguyên, số nhỏ hơn 0 hoặc lớn hơn
hoặc bằng số lượng phần tử có trong str_list: chuỗi sẽ được thêm vào cuối danh sách
+ Ngược lại: chuỗi được thêm vào danh sách tại vị trí index
lOMoARcPSD|59149108
//Ly d liu t textbox string chuoi =
txtInput.Text; int index = 0;
//Kim tra các giá tr ca index phù hp không? (là s nguyên, nm trong khoảng 0 đến n-1
//Vi n là s ng phn t ca BindingList
//Nếu index không hp l thì chui s đưc thêm vào v trí cui danh sách if (!Int32.TryParse(txtIndex.Text,
out index) || index < 0 || index >= str_list.Count)
{
str_list.Add(chuoi);
} else {
str_list.Insert(index, chuoi);
}
txtInput.Text = string.Empty; txtIndex.Text = string.Empty;
txtInput.Focus();
Sự kiện click của nút btnRemove: xóa dữ liệu tại vị trí index
+ Nếu index không hợp lệ: xóa vị trí cuối cùng
+ Ngược lại xóa tại index
if (str_list.Count != 0)
{
int index = 0;
if (!Int32.TryParse(txtIndex.Text, out index) || index < 0 || index >=
str_list.Count)
index = str_list.Count - 1;
if (index >= 0) str_list.RemoveAt(index);
}
txtInput.Text = string.Empty; txtIndex.Text = string.Empty;
txtInput.Focus();
Sự kiện click của nút btnUpdate: cập nhật dữ liệu tại vị trí index hợp lệ
string chuoi = txtInput.Text; int index = 0;
if (Int32.TryParse(txtIndex.Text, out index) && index >= 0 && index < str_list.Count)
str_list[index] = chuoi;
txtInput.Text = string.Empty; txtIndex.Text = string.Empty;
txtInput.Focus();
6. Bài tập mở rộng
Mở rộng bài tập trong mục 5 với các phần tử BindingList là các đối tượng của lớp
Book
Class Book được định nghĩa như sau
lOMoARcPSD|59149108
internal class Book
{
private string _title; private int _price;
public Book(string title, int price)
{
this._title = title; this._price = price;
}
public string Title
{
get { return _title; } set { _title = value; }
}
public int Price
{
get { return _price; } set { _price =
value; }
}
public override string ToString()
{
return Title + " - " + Price.ToString("#,###"); }
}
Form được thiết kế như sau:
Dựa trên bài 5, thực hiện thêm sửa và cập nhật

Preview text:

lOMoARcPSD| 59149108
BUỔI 3: ARRAYLIST, LIST, BINDINGLIST
1. Collection và Generic 1.1. Collection
− Collection là một tập hợp các dữ liệu không cùng kiểu.
− Ưu điểm: khả năng tương tác và thay đổi dữ liệu bên trong ngay tại thời điểm chạy (runtime).
− Thuộc thư viện System.Collections
− Các lớp Collection được sử dụng cho nhiều mục đích khác nhau như cấp phát bộ nhớ
động cho các phần tử, hay truy cập một danh sách các item dựa trên chỉ mục, …
− Các Collection phổ biến: ArrayList, Hashtable, DictionaryEntry,
SortedList, Stack, Queue, BitArray 1.2. Generic
− Được giới thiệu từ C# 2.0. Generic cho phép xác định một class với trình giữ chỗ
(placeholders) cho fields, methods, parameters, …
− Generic thay thế các placeholders này bằng một số loại dữ liệu cụ thể tại thời gian biên dịch (compile time).
− Generic được định nghĩa bằng cách sử dụng dấu ngoặc nhọn <>
− Đặc điểm của generic:
+ Giúp tối đa hóa sử dụng lại code (chỉ cần viết 1 hàm có thể tái sử dụng cho nhiều
kiểu dữ liệu), an toàn và tăng tốc độ.
+ Có thể dùng generic với: interfaces, classes, methods, events, delegates, structs. + Có
thể dùng generic với: interfaces, classes, methods, events, delegates, structs.
+ Có thể lấy thông tin của kiểu dữ liệu được sử dụng bởi generic ở thời điểm runtime bằng Reflection.
− Các Generic collections được sử dụng phổ biến: List,
DictionaryTValue>, Hashset, SortedList, Stack, Queue 2. ArrayList
− Là một collection (không phải generic) − Kích thước tăng tự động
− Có thể được sử dụng để thêm dữ liệu chưa biết kiểu và kích thước − Tạo một ArrayList lOMoARcPSD| 59149108 using System.Collections;
ArrayList arList = new ArrayList(); // hoặc var arList = new ArrayList();
− Thêm phần tử vào ArrayList using System.Collections;
ArrayList arList = new ArrayList();
arList.Add(1); arList.Add(“Hello”);
arList.Add(true); arList.Add(4.5); arList.Add(null); Hoặc using System.Collections;
ArrayList arList = new ArrayList(){ 2, “Hello”, “ ”, true, 4.5, null};
− Truy cập vào ArrayList:
+ Thực thi giao diện IList
+ Sử dụng index, tương tự mảng thông thường + Ép kiểu loại phù hợp hoặc sử dụng biến var
var arlist = new ArrayList() {1, "Bill", 300, 4.5f };
int firstElement = (int) arlist[0]; //returns 1
string secondElement = (string) arlist[1]; //returns "Bill"
//int secondElement = (int) arlist[1]; //Error: cannot cover string
to int var firstElement = arlist[0]; //returns 1 var secondElement = arlist[1]; //returns "Bill"
//var fifthElement = arlist[5]; //Error: Index out of range arlist[0] = "Steve"; arlist[1] = 100;
//arlist[5] = 500; //Error: Index out of range − Duyệt ArrayList lOMoARcPSD| 59149108
ArrayList arlist = new ArrayList() {1, "Bill", 300, 4.5F}; foreach (var item in arlist)
Console.Write(item + ", "); //output: 1, Bill, 300, 4.5,
− Thêm phần tử vào ArrayList
+ Cấu trúc: void Insert(int index, Object value)
ArrayList arlist = new ArrayList() {1, "Bill", 300,
4.5F}; arlist.Insert(1, "Second Item"); foreach (var val in arlist) Console.WriteLine(val);
+ Thêm một collection: InsertRange()
− Xóa phần tử: Remove(), RemoveAt(), RemoveRange
ArrayList arlist = new ArrayList() {1, null, "Bill", 300, 4.5F, “ ”,
300 }; arlist.Remove(null); //xóa phần tử null đầu tiên
arlist.RemoveAt(4); //xóa phần tử tại index 4
arlist.RemoveRange(0, 2); //Xóa 02 phần tử bắt đầu từ index 0
− Kiểm tra phần tử trong ArrayList
ArrayList arlist = new ArrayList() {1, null, "Bill", 300, 4.5F, “ ”, 300 };
Console.WriteLine(arList.Contains(300)); // true
Console.WriteLine(arList.Contains(10)); // false
− Các thuộc tính của ArrayList: Capacity, Count, IsFixedSize, IsReadOnly, Item
− Các phương thức: Add()/AddRange(), Insert()/InsertRange(),
Remove()/RemoveRange(), RemoveAt(), Sort(), Reverse(),
Contains(), Clear(), CopyTo(), GetRange(), IndexOf(), ToArray() 3. List
− Tập hợp các đối tượng có thể được truy cập bằng chỉ mục và có các phương pháp sắp
xếp, tìm kiếm và sử đổi.
− Phiên bản generic của ArrayList, thuộc không gian System.Collections.Generic − Tạo một List lOMoARcPSD| 59149108
List primeNumbers = new List(); primeNumbers.Add(1);
primeNumbers.Add(3); primeNumbers.Add(5); primeNumbers.Add(7);
var cities = new List(); cities.Add("New York");
cities.Add("London"); cities.Add("Mumbai");
cities.Add("Chicago"); cities.Add(null);
var bigCities = new List(){"New York", "London", "Mumbai", "Chicago"};
var students = new List() { new
Student(){ Id = 1, Name="Bill"}, new
Student(){ Id = 2, Name="Steve"}, new
Student(){ Id = 3, Name="Ram"}, new
Student(){ Id = 4, Name="Abdul"} };
− Thêm một Array vào List: void AddRange(IEnumerable collection)
string[] cities = new string[3]{ "Mumbai", "London", "New York" };
var popularCities = new List();
popularCities.AddRange(cities); var favouriteCities = new List();
favouriteCities.AddRange(popularCities);
− Truy cập vào một List
List numbers = new List() { 1, 2, 5, 7, 8, 10 };
Console.WriteLine(numbers[0]); // prints 1
Console.WriteLine(numbers[1]); // prints 2
Console.WriteLine(numbers[2]); // prints 5
Console.WriteLine(numbers[3]); // prints 7
for(int i = 0; i < numbers.Count; i++)
Console.WriteLine(numbers[i]); − Chèn phần tử lOMoARcPSD| 59149108
var numbers = new List(){ 10, 20, 30, 40 };
numbers.Insert(1, 11);// chèn 11 vào index 1: sau 10 foreach (var num in numbers) Console.Write(num); − Xóa phần tử
var numbers = new List(){ 10, 20, 30, 40,
10 }; numbers.Remove(10); numbers.RemoveAt(2);
//numbers.RemoveAt(10); //throws ArgumentOutOfRangeException foreach (var el in intList) Console.Write(el); − Kiểm tra phần tử
var numbers = new List(){ 10, 20, 30, 40 };
numbers.Contains(10); // returns true numbers.Contains(11);
// returns false numbers.Contains(20); // returns true
4. Yêu cầu thực hành
a) Thực hiện các ví dụ phần 2 và 3 trong C# (Console)
b) Viết chương trình cho phép người dùng nhập vào các số nguyên (không giới hạn lần
nhập) với câu lệnh sau:
sum: hiển thị tổng các số đã nhập đến hiện tại
view: hiển thị tất cả các số đã nhập end: thoát
- Hiển thị menu gồm 4 tùy chọn: append, sum, view, end với
+ append: nhập vào số nguyên và thêm vào danh sách
+ sum: hiển thị tổng số có trong danh sách
+ view: hiển thị danh sách số nguyên
+ end: kết thúc chương trình lOMoARcPSD| 59149108
c) Viết một struct Point3D biểu diễn một điểm trong không gian 3D với tọa độ x, y, z.
Viết một chương trình với menu cho phép người dùng thêm 1 điểm, hiển thị tất cả các
điểm và thoát chương trình. struct Point3D {
public int x; public int y; public int z; }
d) Mở rộng câu b với các câu lệnh:
del xx: xóa phần tử tại vị trí xx insert a b:
chèn phần tử có giá trị b vào vị trí a lOMoARcPSD| 59149108 5. BindingList
Được sử dụng làm lớp cơ sở để tạo cơ chế liên kết dữ liệu hai chiều; thường được sử
dụng trong gắn kết dữ liệu (data binding) trong Windows Forms để cung cấp nguồn dữ
liệu động cho các điều khiển như DataGridView, ListBox, ComboBox Yêu cầu thực hiện:
− Tạo một form hiển thị danh sách các chuỗi được nhập từ bàn phím Control Name Properties Form frmMain Name: frmMain Text: Minh họa Binding List Textbox (trái) txtInput Name: txtInput Tabindex: 0 Textbox (phải) txtIndex Name: txtIndex Tabindex: 1 lOMoARcPSD| 59149108 Button btnAdd Name: btnAdd Control Name Properties Text: Thêm Tabindex: 2 Button btnRemove Name: btnRemove Text: Xóa Tabindex: 3 Button btnUpdate Name: btnUpdate Text: Sửa Tabindex: 4 ListBox lstbList Name: lstbList Tabindex: 5
− Trong class frmMain khai báo một đối tượng BindingList private BindingList str_list;
− Đối tượng được khởi tạo trong hàm khởi tạo public frmMain() { InitializeComponent(); str_list= new BindingList(); }
− Khi sự kiện load của form được gọi, chỉ định nguồn dữ liệu của listbox là BindingList đã tạo
lstbList.DataSource = str_list;
− Sự kiện click của nút btnAdd: khi người dùng chọn Thêm dữ liệu được nhập
trong ô txtInput sẽ được thêm vào str_list và hiển thị trong listbox
+ Nếu người dùng nhập index không là số nguyên, số nhỏ hơn 0 hoặc lớn hơn
hoặc bằng số lượng phần tử có trong str_list: chuỗi sẽ được thêm vào cuối danh sách
+ Ngược lại: chuỗi được thêm vào danh sách tại vị trí index lOMoARcPSD| 59149108
//Lấy dữ liệu từ textbox string chuoi = txtInput.Text; int index = 0;
//Kiểm tra các giá trị của index phù hợp không? (là số nguyên, nằm trong khoảng 0 đến n-1
//Với n là số lượng phần tử của BindingList
//Nếu index không hợp lệ thì chuỗi sẽ được thêm vào vị trí cuối danh sách if (!Int32.TryParse(txtIndex.Text,
out index) || index < 0 || index >= str_list.Count) { str_list.Add(chuoi); } else {
str_list.Insert(index, chuoi); }
txtInput.Text = string.Empty; txtIndex.Text = string.Empty; txtInput.Focus();
− Sự kiện click của nút btnRemove: xóa dữ liệu tại vị trí index
+ Nếu index không hợp lệ: xóa vị trí cuối cùng
+ Ngược lại xóa tại index if (str_list.Count != 0) { int index = 0;
if (!Int32.TryParse(txtIndex.Text, out index) || index < 0 || index >= str_list.Count) index = str_list.Count - 1;
if (index >= 0) str_list.RemoveAt(index); }
txtInput.Text = string.Empty; txtIndex.Text = string.Empty; txtInput.Focus();
− Sự kiện click của nút btnUpdate: cập nhật dữ liệu tại vị trí index hợp lệ
string chuoi = txtInput.Text; int index = 0;
if (Int32.TryParse(txtIndex.Text, out index) && index >= 0 && index < str_list.Count) str_list[index] = chuoi;
txtInput.Text = string.Empty; txtIndex.Text = string.Empty; txtInput.Focus();
6. Bài tập mở rộng
Mở rộng bài tập trong mục 5 với các phần tử BindingList là các đối tượng của lớp Book
− Class Book được định nghĩa như sau lOMoARcPSD| 59149108 internal class Book {
private string _title; private int _price;
public Book(string title, int price) {
this._title = title; this._price = price; } public string Title {
get { return _title; } set { _title = value; } } public int Price {
get { return _price; } set { _price = value; } }
public override string ToString() {
return Title + " - " + Price.ToString("#,###"); } }
− Form được thiết kế như sau:
− Dựa trên bài 5, thực hiện thêm sửa và cập nhật