C# Cơ bản .NET Core §1 Cài đặt, chương trình C# đầu tiên §2 Biến, kiểu dữ liệu và nhập/xuất §3 Toán tử số học và gán §4 So sánh, logic và lệnh if, switch §5 Vòng lặp for, while §6 Phương thức - Method §7 Phương thức - Delegate §8 Lớp - Class §9 Namespace §10 Partial, Nested §11 Kiểu giá trị, tham chiếu §12 Kiểu vô danh và dynamic §13 Biểu thức lambda §14 Event §15 Hàm hủy - Quá tải toán tử - thành viên tĩnh - indexer §16 null và nullable §17 Mảng §18 Chuỗi ký tự §19 Tính kế thừa §20 Phương thức khởi tạo §21 Tính đa hình - abstract - interface §22 Struct và Enum §23 Ngoại lệ Exeption §24 IDisposable - using §25 File cơ bản §26 FileStream §27 Generic §28 Collection - List §29 SortedList §30 Queue / Stack §31 Linkedlist §32 Dictionary - HashSet §33 Phương thức mở rộng §34 ObservableCollection §35 LINQ §36 (Multithreading) async - bất đồng bộ §37 Type §38 Attribute Annotation §39 DI Dependency Injection §40 (Multithreading) Parallel §41 Thư viện lớp §42 (Networking) HttpClient §43 (Networking) HttpMessageHandler §44 (Networking) HttpListener §45 (Networking) Tcp TcpListenerr/TcpClient §46 (ADO.NET) SqlConnection §47 (ADO.NET) SqlCommand §48 (EF Core) Tổng quan §49 (EF Core) Tạo Model §50 (EF Core) Fluent API §51 (EF Core) Query §52 (EF Core) Scaffold §53 (EF Core) Migration §54 (ASP.NET CORE) Hello World! §55 (ASP.NET CORE) Middleware §56 (ASP.NET CORE) Map - Request - Response §57 (ASP.NET CORE) IServiceCollection - MapWhen §58 (ASP.NET CORE) Session - ISession §59 (ASP.NET CORE) Configuration §60 (ASP.NET CORE) Gửi Mail §61 (ASP.NET RAZOR) Khởi tạo và Route §62 (ASP.NET RAZOR) Cú pháp Razor §63 (ASP.NET RAZOR) Layout trong ASP.NET Core §64 (ASP.NET RAZOR) Partial §65 (ASP.NET RAZOR) ViewComponent §66 (ASP.NET RAZOR) TagHelper §67 (ASP.NET RAZOR) PageModel §68 (ASP.NET RAZOR) Model Binding §69 (ASP.NET RAZOR) HTML Form, Validation §70 (ASP.NET RAZOR) Upload File §71 (ASP.NET RAZOR) HtmlHelper §72 (ASP.NET RAZOR) Entity Framework §73 (ASP.NET RAZOR) Paging §74 (ASP.NET RAZOR) Identity (1) - Register, Login, Logout §75 (ASP.NET RAZOR) Identity (2) Lockout, Reset Password §76 (ASP.NET RAZOR) Identity (3) Google Login §77 (ASP.NET RAZOR) Identity (4) Facebook Login §78 (ASP.NET RAZOR) Identity (5) profile, password, email ... §79 (ASP.NET RAZOR) Identity (6) Role §80 (ASP.NET RAZOR) Identity (7) Role-based Authorization §81 (ASP.NET RAZOR) Identity (8) RoleClaim §82 (ASP.NET RAZOR) Identity (9) Authorization Handler §83 (ASP.NET RAZOR) IAuthorizationService §84 (ASP.NET MVC) Controller - View §85 (ASP.NET MVC) MVC Route
null và nullable (Bài trước)
(Bài tiếp) Chuỗi ký tự

Mảng - Khai báo mảng trong C#

Mảng là một cấu trúc dữ liệu được sử dụng dụng để lưu trữ một tập dữ liệu cùng kiểu. Ví dụ, bạn có 50 biến kiểu int chúng là những mã số sinh viên chẳng hạn, nếu không dùng mảng thì bạn cần khai báo và nhớ 50 biến kiểu int. Thay vì 50 biến khác nhau đó, hãy tập hợp chúng lại lưu vào một biến mảng kiểu int có 50 phần tử.

Cú pháp khai báo biến mảng là chỉ ra kiểu phần tử mảng - tiếp theo là ký hiệu []

int[] bienMang; // khai báo biến mảng kiểu phần tử là int (chưa khởi tạo)

Khởi tạo mảng

Muốn khởi tạo một đối tượng mảng để gán vào biến mảng thì thực hiện như sau, ví dụ sau khởi tạo ra đối tượng mảng kiểu int, có 5 phần tử

bienMang  = new int[5];     
// có thể khởi tạo ngay khi khai báo int[] bienMang = new int[5];
string[] studentNames = new string[10];

Khởi tạo new datatype[n] tạo ra mảng có kiểu datatype và có thể lưu n phần tử

Khi khởi tạo - nó tạo ra mảng có số phần tử chỉ định, các phần tử của mảng có giá trị khởi tạo mặc định tùy vào kiểu dữ liệu sau đó bạn có thể cần gán giá trị lưu trữ trong các phần tử (nói ngay sau đây). C# hỗ trợ ngay khi khởi tạo mảng ta gán luôn các giá trị cụ thể vào mảng bằng cách mở ra ký hiệu {} trong nó liệt kê các giá trị lưu trữ của mảng.

Ví dụ:

// mảng 3 phần tử chuỗi ký tự, mỗi phần tử được gán ngay giá trị chuỗi cụ thể
string[] productNames = new string[3] {"Iphone", "Samsung", "Nokia"};
// mảng 3 phần tử double, mỗi phần tử được gán giá trị luôn
double[] productPrices = new double[3] {100, 200.5, 10.1};

Khi mảng được báo và khởi tạo luôn như vậy, không nhất thiết chỉ ra số lương phần tử ở [], vì số lượng phần tử sẽ lấy theo số giá trị khởi tạo trong {}, viết như sau là tương đương phần trên

string[] productNames = new string[] {"Iphone", "Samsung", "Nokia"};
double[] productPrices = new double[] {100, 200.5, 10.1};

Cách này thậm chỉ còn bỏ luôn cả toán tử new thì nó cũng ngầm định sử dụng khởi tạo như trên

string[] productNames = {"Iphone", "Samsung", "Nokia"};
double[] productPrices = {100, 200.5, 10.1};
Các giá trị khởi tạo gán cho phần tử mảng được liệt kế cách nhau bởi , và đặt trong {}

Truy cập phần tử mảng

Các phần tử mảng được truy cập thông qua ký hiệu biến-mảng[chỉ-số], trong đó chỉ-số là thứ tự của phần tử trong mảng, các phần tử mảng có chỉ số từ 0 trở đi.

int[] myArray = {1,3,5,19};
chỉ số [0] [1] [2] [3]
giá trị phần tử 1 3 5 19
int a = myArray[2]   // đọc phần tử chỉ số 2 (phần tử thứ 3) của mảng =  5
myArray[3] = 100;   // Gán 100 vào phần tử có chỉ số 3, 19 thay thế bởi 100

Thuộc tính và phương thức đối tượng mảng

Các biến mảng thực chất được tạo ra từ lớp có lơps cơ sở là System.Array, nên nó có các thuộc tính phương thức của lớp này. Một số thuộc tính và phương thức như sau:

Member Nội dung
Length Thuộc tính cho biết số lượng phần tử trong mảng
Rank Thuộc tính cho biết số chiều mảng
Clone() Copy (nhân bản) đối tượng mảng
GetValue(index) Lấy giá trị phần tử trong mảng
Min() Trả về giá trị nhỏ nhất trong mảng
Max() Trả về giá trị lớn nhất trong mảng
Sum() Trả về giá trị tổng cộng các phần tử

Chú ý cần nạp thư viện Linq bằng using System.Linq; ở đầu để có phương thức Max(), Min(), Sum()

Một số phương thức tĩnh trong Array áp dụng vào mảng như:

Member Nội dung
Array.BinarySearch(array, value) Tìm kiếm phần tử trong mảng đã được sắp xếp, trả về chỉ số nếu tìm thấy
CopyTo(array, indexStart) Sao chép phần tử mảng này sang mảng khác
Array.Clear(array, index, length) Thiết lập phần tử mảng nhận giá trị mặc định
bool Exists<T> (array, Predicate<T> match); Kiểm tra có phần tử trong mảng thỏa mãn match
Fill<T> (array, value); Gán các phần tử của mảng bằng value
T Find<T> (array, Predicate<T> match); Tìm phần tử mảng
int FindIndex<T> (array, Predicate<T> match); Tìm phần tử mảng, trả về chỉ số nếu thấy
T[] FindAll<T> (array, Predicate<T> match); Tìm tất cả phần tử mảng
int IndexOf(array, value) Tìm chỉ số của phần tử
ForEach(array, Action<T> action) Thi hành action trên mỗi phần tử
Sort(array) Sắp xếp

Ví dụ, duyệt qua các phần tử mảng kiểu int, và in ra nội dung phần tử

static void testForEach()
{
    int[] numbers = {9, 8, 7, 6, 5, 4, 3, 2, 1 };
    Array.ForEach<int>(numbers, (int n) => {
        Console.WriteLine(n);
    });
}

Ví dụ, tìm các số chẵn (chia hết cho 2) trong mảng số nguyên rồi in kết quả tìm được

static void testFindAll()
{
    int[] numbers = {9, 8, 7, 6, 5, 4, 3, 2, 1 };

    // Định nghĩa Predicate là một delegate tham số kiểu int
    // trả về true nếu số chia hết cho 2
    Predicate<int> predicate =  (int number) => {
        return number % 2 == 0;
    };
    // Tìm các số chẵn
    int[] cacsochan = Array.FindAll(numbers, predicate);

    // In kết quả
    Action<int> printnumber = (int number) => Console.WriteLine(number);
    Array.ForEach(cacsochan, printnumber);
}

Duyệt qua các phần tử mảng

Duyệt qua bằng lệnh for

Bạn có thể dùng for với một biến chạy là chỉ số, chạy từ 0 là chỉ số phần tử đầu tiên cho đến chỉ số của phần tử cuối cùng, chỉ số phần tử cuối cùng có thể xác định bằng số lượng phần tử - 1, số lượng phần tử bạn biết là do khai báo, nếu chưa biết thì lấy bằng thuộc tính .Length

int[] myArray = {1,3,5,19, 10, 20, 40, 40};
int maxIndex = myArray.Length - 1;
for (int idx = 0; idx <= maxIndex; idx ++) {
    Console.WriteLine(myArray[idx]);
}

Kết quả

1
3
5
19
10
20
40
40

Duyệt qua bằng lệnh foreach

foreach cung cấp cách thức gọn hơn để duyệt qua các phần tử mảng

int[] myArray = {1,3,5,19, 10, 20, 40, 40};
foreach (int element in myArray)
{
    Console.WriteLine(element);
}

Kết quả xuất ra như trên, duyệt bằng foreach thì mỗi phần tử được trích xuất ra, gán vào biến cục bộ có tên element (element có kiểu dữ liệu giống kiểu trong phần tử mảng)

Có thể dùng var để khai báo biến có kiểu ngầm định

foreach (var e in vararry) {
   // ...
}

Ví dụ

int[] myArray = {1,3,5,19, 10, 20, 40, 40};
int sum = 0;
foreach (var e in myArray)
{
    sum += e;
}
Console.WriteLine(sum);   // 138

Mảng nhiều chiều (rank)

Các phần trước, đã làm việc với mảng 1 chiều - nó như là các vector. Bạn có thể tạo mảng hai chiều, ba chiều ...

Mảng hai chiều - giống như bảng dữ liệu - ma trận số.

Cú pháp để khai báo mảng nhiều chiều như sau:

type[, , … ,] varname = new type[size1, size2, …, sizeN];

Ví dụ khai báo mảng số nguyên hai chiều 3x4 (3 hàng 4 cột)

int[,] myvar = new int[3,4];

Để truy cập vào phần tử cụ thể của mảng, chỉ ra số chỉ số (bằng số chiều):

myvar[0,0] =  1;    // hàng 1, cột 1
myvar[2,3] =  3;    // hàng 3, cột 4
int[,] myvar = new int[3,4] {{1,2,3,4}, {0,3,1,3}, {4,2,3,4}};          // khai báo và khởi tạo mảng 2 chiều

for (int i = 0; i <= 2; i ++)                                           // duyệt qua từng hàng
{
    for(int j = 0; j <=3; j++)                                          // duyệt qua từng cột
    {
        Console.Write(myvar[i,j] + " ");
    }
    Console.WriteLine();
}
// 1 2 3 4
// 0 3 1 3
// 4 2 3 4
    

Mảng trong mảng

Khi một mảng nào đó, mà các phần tử của mảng lại là các mảng - đó là mảng trong mảng - jagged

Ví dụ, nếu ký hiệu int[] là kiểu mảng mà các phần tử số nguyên, vậy khi viết int[][] sẽ là kiểu mảng mà các phần tử lại là mảng số nguyên

 int[][] myArray = new int[][] {
                                new int[] {1,2},
                                new int[] {2,5,6},
                                new int[] {2,3},
                                new int[] {2,3,4,5,5}
                               };

foreach (var arr in myArray) {
    foreach (var e in arr) {
        Console.Write(e + " ");
    }
    Console.WriteLine();
}

// 1 2
// 2 5 6
// 2 3
// 2 3 4 5 5

Tham khảo mã nguồn CS012_Array (git) hoặc tải về tại ex012-ar

Đăng ký theo dõi ủng hộ kênh
null và nullable (Bài trước)
(Bài tiếp) Chuỗi ký tự