bool b = booleanArray[7];
Trong managed code, CLR sẽ kiểm tra để đảm bảo là các phần tử truy nhập nằm trong giới hạn của mảng, nếu không thì một ngoại lệ sẽ được ném ra: IndexOutOfRangeException.
Khi làm việc với mảng, đôi khi chúng ta cần thay đổi kích thước của mảng. Để làm được điều này, chúng ta phải tạo một thể hiện mới của mảng với kích thước mới, sao chép nội dung mảng cũ sang mảng mới. Đoạn code sau mô tả quá trình đó:
// Create an integer array with three elements
// Redimension message to a 10 element array
int [] temp = new int[10];
// Copy the fib array to temp
Sau dòng code cuối thì mảng fib có thể tham chiếu được tới 10 phần tử. Giá trị từ 3 – 9 sẽ mang giá trị mặc định của kiểu Int32 là 0
Tạo Cấu trúc dữ liệu thực thi an toàn, có thể tái sử dụng
Khi tạo một cấu trúc dữ liệu cho một vấn đề nào đó, thường thì cấu trúc đó được tùy chỉnh theo yêu cầu của công việc. Ví dụ, để quản lí bảng lương nhân viên, các giá trị đầu vào là các nhân viên, chúng ta có thể tạo một lớp Employee với các phương thức và thuộc tính phù hợp. Và để biểu diễn một tập hợp các nhân viên, chúng ta có thể sử dụng một mảng Employee, nhưng bạn lại cần có thêm các chức năng bổ sung mà không muốn quan tâm đến việc thay đổi kích thước mảng khi cần thiết. Một tùy chọn đó là tự tạo một cấu trúc dữ liệu riêng cho kiểu Employee, thêm vào đó các chức năng cần thiết như tìm kiếm, tăng kích thước….
Cấu trúc này tỏ ra hữu dụng trong ứng dụng của bạn nhưng khi đem sử dụng cho các ứng dụng khác thì lại không được vì nó chỉ lưu trữ các phần tử là kiểu Employee. Để tạo cấu trúc dữ liệu thêm linh hoạt, ta có thể tạo một mảng của các thể hiện Object. Bởi vì tất cả các kiểu dữ liệu đều là dẫn xuất từ kiểu Object nên nó có thể lưu bất kì giá trị nào. .NET Framework cung cấp một cấu trúc cho việc này: lớp System.Collections.ArrayList. ArrayList chứa một mảng các phần tử có kiểu là Object nên nó có thể lưu bất kì kiểu giá trị nào: strings, integers, đối tượng FileInfo, các thể hiện của Form ….
Mặc dù ArrayList tỏ ra khá hữu hiệu và linh hoạt nhưng lại phải đổi lại bằng hiệu năng của ứng dụng. Vì ArrayList lưu mảng các object, và khi đọc giá trị thì phải ép kiểu giá trị. Một mảng ArrayList thì dù cho bạn không có lưu trữ bất cứ phần tử nào thì mỗi phần tử là một tham chiếu tới một kiểu giá trị được boxed (boxed value type) => tốn bộ nhớ.
Sử dụng ArrayList với số lượng phần tử lớn có thể làm chậm việc thực thi chương trình. Ngoài ra, vì ArrayList cho phép bất cứ kiểu giá trị nào cũng có thể được thêm vào nên sẽ không có lỗi xảy ra khi thêm một kiểu không hợp lệ. Các lỗi này sẽ không xuất hiện đến khi kiểm tra hoặc đem ra sử dụng.
Tuy nhiên, trong .NET Framework 2.0, chúng ta có Generics để giải quyết vấn đề của ArrayList. Generics là một namespace cho phép tạo một cấu trúc dữ liệu theo một cách khác. Developer có thể tùy chọn kiểu dữ liệu sử dụng . Để hiểu rõ hơn thì chúng ta xét một ví dụ:
public class TypeSafeList<T>
T[] innerArray = new T[0];
// see if array needs to be resized
if (currentSize == capacity)
capacity = capacity == 0 ? 4 : capacity * 2; // double capacity
T[] copy = new T[capacity]; // create newly sized array
Array.Copy(innerArray, copy, currentSize); // copy over the array
innerArray = copy; // assign innerArray to the new, larger array
innerArray[currentSize] = item;
if (index < 0 || index >= currentSize)
throw new IndexOutOfRangeException();
return innerArray[index];
if (index < 0 || index >= currentSize)
throw new IndexOutOfRangeException();
innerArray[index] = value;
public override string ToString()
string output = string.Empty;
for (int i = 0; i < currentSize - 1; i++)
output += innerArray[i] + ", ";
return output + innerArray[currentSize - 1];
Tại dòng đầu tiên, chúng ta có thành phần định nghĩa kiểu T. Developer sẽ dùng nó để chỉ định một kiểu, mà ở đây chúng ta định danh là T. Chúng ta hoàn toàn có thể dùng các tên khác thay cho T, và biến này có thể được sử dụng trong các phương thức và thuộc tính.
Để khai báo biến cho class này, developer cần chỉ định kiểu T, như:
TypeSafeList<type> varibaleName;
Đoạn code sau mô tả việc tạo một thể hiện của TypeSafeList lưu trữ số nguyên và đưa giá trị là 25 số Fibonacci vào:
TypeSafeList<int> fib = new TypeSafeList<int>();
fib.Add(fib[i-1] + fib[i-2]);
Console.WriteLine(fib.ToString());
Lợi ích của việc sử dụng Generics là:
-An toàn kiểu: developer chỉ có thể thêm vào một kiểu được chỉ định.
-Performance: chương trình thực thi nhanh hơn và hiệu quả hơn
Rất nhiều cấu trúc dữ liệu, ví dụ như cây nhị phân, chúng ta sẽ dùng tới Generics
List: Mảng đồng nhất, tự thay đổi số chiều.
Trong phần trước, chúng ta đã tạo ra một lớp TypeSafeList, tuy nhiên, .NET Framework cung cấp sẵn một lớp tương tự như vậy cho chúng ta mà chúng ta không cần quan tâm nhiều đến việc viết code. Đó là lớp List, được chứa trong namespace System.Collections.Generics
Để tạo một thể hiện của List, ta làm giống như ví dụ ở phần trước:
//Tạo một danh sách các số nguyên
List<int> myFavouriteIntegers = new List<int>();
//Tạo một danh sách chuỗi
List<string> friendsNames = new List<string>();
Khi khởi tạo, chúng ta không cần chỉ ra kích thước của List (mặc dù chúng ta có thể chỉ định một kích thước mặc định trước qua constructor hoặc qua thuộc tính List’s Capacity). Để thêm vào một phần tử, ta dùng phương thức Add(), và chúng ta có thể truy cập trực tiếp và các phần tử thông qua chỉ số của phần tử đó. Sau đây là một đoạn code mô tả việc tạo một List các số nguyên, và sau đó là thêm, đọc, ghi giá trị:
// Create a List of integers
List<int> powersOf2 = new List<int>();
// Add 6 integers to the List
// Change the 2nd List item to 10
int sum = powersOf2[2] + powersOf2[3];
List cung cấp cho ta nhiều phương thức hỗ trợ cho các công việc thường làm. Ví dụ, muốn tìm một phần tử trong một mảng, bạn cần viết một vòng lặp for để thực hiện. Trong List, bạn chỉ cần đơn giản gọi thủ tục Contains() để xem có phần tử nào đó trong mảng không, hay IndexOf() để tìm vị trí của phần tử. Lớp List cũng có phương thức BinarySearch() để tìm một phần tử trong mảng đã được sắp xếp, và các phương thức Find(), FindAll(), Sort(), ConvertAll().