SetProperty and GetProperty with C# Reflection

I’ll make a post soon, comparing Ruby on Rails to C# with ASP.NET MVC, but this here is atomic and might be of help for one or two readers.

If you want to set and get properties in C# in a type-agnostic way, these are the functions you want to put into a library class somewhere (or, as I did, into the class that uses them):

private object getProperty(object containingObject, string propertyName)
{
    return containingObject.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, containingObject, null);
}

private void setProperty(object containingObject, string propertyName, object newValue)
{
    containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { newValue });
}
Private Function getProperty(containingObject As Object, propertyName As String) As Object
    Return containingObject.[GetType]().InvokeMember(propertyName, BindingFlags.GetProperty, Nothing, containingObject, Nothing)
End Function

Private Sub setProperty(containingObject As Object, propertyName As String, newValue As Object)
    containingObject.[GetType]().InvokeMember(propertyName, BindingFlags.SetProperty, Nothing, containingObject, New Object() {newValue})
End Sub

[Programming in C#] Bài 6: Lập trình hướng đối tượng trong C#

1. Lập trình hướng đối tượng là gì
- Lập trình hướng đối tượng là phương pháp lập trình thay vì tập trung vào việc phân tích và thực hiện các chức năng (thủ tục) của chương trình thì chúng ta tiến hành tìm hiểu, phân tích các thực thể, các đối tượng tham gia vào chương trình. Từ đó chúng thực hiện xây dựng các đặc trưng, các hành vi của các đối tượng. Và chương trình chẳng qua là mô phỏng các tương tác giữa các đối tượng đó mà thôi.
- Phương pháp lập trình hướng đối tượng tạo ra nhiều cái ưu điểm ưu việt hơn so với phương pháp lập trình thủ tục. Một trong những ưu điểm lớn nhất của phương pháp lập trình hướng đối tượng là khả năng sử dụng lại code (reuse code).

2. Các khái niệm thiết yếu trong lập trình hướng đối tượng
- Đối tượng (object): là những sự vật, sự việc, hiện tượng xảy ra trong thế giới thực mà con người có thể nhìn thấy, sờ thấy, cảm nhận thấy. Một số VD về các đối tượng: đồng hồ treo tường, máy chiếu, bàn học, bức tranh, học viên Nguyễn Văn Mạnh, …..
- Lớp (class): là một mẫu (template) hoặc là một plan (kế hoạch) cho việc xây dựng các đối tượng. Lớp là một sự trừu tượng hóa của các đối tượng có chung đặc trưng và hành vi. Một số VD về lớp: Bàn, Học viên, Nhân viên, ….
Một đối tượng là một thể hiện cụ thể của một lớp.
- Đặc trưng (characteristic): là những tính chất của các đối tượng. VD: màu sắc, chiều dài, chiều rộng, tuổi, địa chỉ ….
Mặc định thì các đặc trưng là private.
- Hành vi (behavior): là những hành động của đối tượng. VD: các hành vi của Sinh viên: đăng ký học tiếng Anh, nhảy, diễn thuyết, trình bày báo cáo tốt nghiệp…
Mặc định các hành vi là public.
- Kế thừa (inheritance): là một cơ chế cho phép các đối tượng có thể kế thừa tất cả những đặc trưng và hành vi của các đối tượng khác. VD: một nhân viên kế thừa tất cả các đặc trưng của một người. Một trưởng phòng kế thừa tất cả các đặc trưng của một nhân viên.
- Tính đóng gói (encapsulation): là khả năng một đối tượng có thể che dấu tất cả các đặc trưng cũng như các hành vi của họ bên trong 1 lớp.
- Tính đa hình (polymorphism): là khả năng một hành vi của một đối tượng có thể được thực hiện dưới nhiều hình thức khác nhau.
- Tính trừu tượng (abstraction): là khả năng cho phép thực hiện trừu tượng hóa tất cả các đối tư���ng trong thế giới thực với những hành vi và đặc trưng chung vào trong lập trình và cho phép tạo ra các lớp mà có thể được kế thừa.

3. Các bước thực hiện tiếp cận phương pháp lập trình hướng đối tượng
- Phân tích đặc tả của bài toán lập trình để tìm ra các đối tượng, các lớp.
Để tìm được các đối tượng, các lớp chúng ta dựa vào các danh từ hoặc cụm danh từ trong đặc tả bài toán.
VD: áp dụng đặc tả bài toán PCS_Lab5 trong buổi trước chúng ta tìm ra các danh từ, cụm danh từ sau:
Chương trình, Sinh viên, Chức năng, Menu, Mục chọn (MenuItem),…..
- Tìm ra các hành vi, các đặc trưng của các đối tượng.
VD: đối tượng Menu có các đặc trưng và các hành vi sau:
+ Các đặc trưng:

* Danh sách các mục chọn.
* Mục được chọn.

+ Các hành vi:

* Hiển thị.
* Thêm mục chọn.
* Bớt mục chọn.

………………………………
- Tìm ra mối quan hệ, sự kết hợp, tương tác giữa các đối tượng.
- Tiến hành viết code để xây dựng chương trình.

4. Thực hiện lập trình hướng đối tượng trong C#
- Để thực hiện lập trình hướng đối tượng thì việc đầu tiên chúng ta phải xác định và tạo ra các lớp (class).
- Để tạo ra một lớp trong C# chúng ta thực hiện như sau:

* Click phải chuột vào Project chọn Add -> Class.
* Gõ tên lớp.
* Nhấn OK.

Cú pháp khai báo 1 lớp trong C#:
[bổ từ truy cập] class [tên lớp]
{
}
Trong đó:
[bổ từ truy cập]: là từ khóa để chỉ ra phạm vi truy cập của lớp. Các phạm vi truy cập của lớp có thể là 1 trong các phạm vi sau:

* public
* internal
* private

[tên lớp]: tuân theo quy tắc định danh.
VD: để khai báo lớp Menu chúng ta sử dụng đoạn code.
public class Menu
{
}
- Các thành phần của một lớp (members of class):
Một lớp có thể có 4 thành phần:

* Các biến để lưu trữ các đặc trưng của đối tượng (variables).

Cú pháp để khai báo các đặc trưng của đối tượng:
[bổ từ truy cập] [kiểu dữ liệu] [tên biến];
Trong đó:
[bổ từ truy cập]: chỉ ra phạm vi truy cập của biến. Các phạm vi có thể:

* private: một biến được chỉ ra private chỉ có thể được truy cập bởi các thành phần trong lớp đó.
* protected: một biến được khai báo là protected chỉ có thể được truy cập bởi các thành phần bên trong lớp đó và các thành phần trong lớp kế thừa lớp đó.
* internal: một biến internal có thể được truy cập bởi các thành phần trong 1 lớp, các thành phần trong lớp kế thừa, các thành phần trong các lớp cùng assembly với nó.
* public: một biến là public thì có thể được truy cập bởi bất kì một thành phần của bất kì một lớp nào.

[kiểu dữ liệu]: là bất kì các kiểu dữ liệu nào được hỗ trợ bởi C#.
[tên biến]: tuân theo quy tắc định danh.
VD: về khai báo các biến.
private int _mucChon;
private ArrayList _danhSachMucChon;

* Các phương thức (methods): là những đoạn code mô phỏng các hành vi của các đối tượng trong lớp.

Cú pháp khai báo phương thức:
[bổ từ truy cập] [kiểu dữ liệu trả về] [tên phương thức] ([danh sách các đối số])
{
[các câu lệnh];
}
Trong đó:
[bổ từ truy cập]: giống với của biến.
[kiểu dữ liệu trả về]: chỉ ra kiểu của giá trị được trả về bởi phương thức, nếu phương thức ko trả về giá trị thì kiểu dữ liệu trả về là void.
[tên phương thức]: tuân theo quy tắc định danh.
[danh sách đối số]: là danh sách các khai báo biến cách nhau bởi dấu phẩy (,).
VD:

public int HienThi()
{
    Console.WriteLine("CAC CHUC NANG CHINH CUA CHUONG TRINH");
    for (int i = 0; i < _danhSachMucChon.Count; i++)
    {
        Console.WriteLine("{0}. {1}", i + 1, _danhSachMucChon[i]);
    }
    Console.Write("Ban chon: ");
    int chon;
    do
    {
        chon = int.Parse(Console.ReadLine());
    }
    while (chon < 1 || chon > _danhSachMucChon.Count);

    return chon;
}

5. Kế thừa (Inheritance) - Kế thừa là một cơ chế cho phép một lớp có tất cả các đặc trưng và hành vi của một lớp khác.
- Kế thừa là một hình thức cho phép chúng ta sử dụng lại code.
- Kế thừa cho phép chúng ta xây dựng các ứng dụng mà ko phải viết code từ đầu, giúp tiết kiệm thời gian, chi phí bỏ ra để xây dựng các ứng dụng.
- Trong C# để thực hiện kế thừa chúng ta dùng cú pháp:
[bổ từ truy cập] class [tên lớp] : [tên lớp được kế thừa]
- Các khái niệm có liên quan đến kế thừa:

* Lớp cha (parent class): là lớp được kế thừa (là lớp có tất cả các hành vi, các đặc trưng được kế thừa), lớp cha còn được gọi là super class hoặc base class (lớp cơ sở).
* Lớp con (child class): là lớp kế thừa tất cả các đặc trưng và hành vi của các lớp khác, lớp con còn được gọi là sub class hoặc derive class (lớp dẫn xuất).

- Một số chú ý về kế thừa trong C#:

* Trong C# chúng ta chỉ có thể kế thừa từ 1 lớp (đơn kế thừa đối với lớp).
* Tuy nhiên chúng ta có thể đa kế thừa đối với giao tiếp (Interface).


6. Tính đa hình (Polymorphism)
- Tính đa hình là khả năng cho phép một hành vi (một phương thức) có thể được thể hiện dưới nhiều hình thức khác nhau.
- Trong C# tính đa hình có thể được cài đặt theo 2 cách:

* Overloading method (quá tải hàm): là khả năng trong một lớp có thể có nhiều phương thức trùng tên với nhau. Có 2 hình thức quá tải hàm:

+ Các hàm trùng tên và số lượng các đối số là khác nhau.
+ Các hàm trùng tên và số lượng các đối số bằng nhau nhưng kiểu dữ liệu của một số các đối số là khác nhau.

* Overidding method (chồng hàm): là khả năng cho phép các lớp con có thể có các phương thức trùng tên với lớp cha.

Để thực hiện chồng hàm thì các hành vi của lớp cơ sở cần phải được đánh dấu bằng từ khóa virtual.
Còn các lớp kế thừa từ lớp cơ sở này muốn thực hiện tính đa hình cho hành vi trên thì phải dùng từ khóa override.

7. Lớp trừu tượng (abstract class)

- Lớp trừu tượng là một lớp được sử dụng để chia sẻ tất cả những hành vi và đặc trưng cho các lớp khác sử dụng.
- Chúng ta ko thể tạo một thể hiện trực tiếp từ một lớp trừu tượng. Muốn tạo ra thể hiện của lớp trừu tượng thì chúng ta phải tạo ra một lớp kế thừa từ lớp trừu tượng.
- Trong C# thì một lớp trừu tượng được đánh dấu bởi từ khóa abstract.

8. Lớp đóng kín (sealed class)
- Lớp đóng kín là lớp mà ko thể có lớp kế thừa.
- Lớp đóng kín được đánh dấu bởi từ khóa sealed.
- Lớp đóng kín thường là lớp được sử dụng để cung cấp các chức năng tiện ích. Những lớp này thường được gọi là Utilities Classes.

9. Giao tiếp (interface)

- Giao tiếp là một tập hợp các thuộc tính và các hành vi cần được thực hiện bởi một lớp nào đó.
- Giao tiếp được sử dụng như một khế ước (giao kèo) để đảm bảo rằng một lớp phải thực hiện những hành vi nhất định nào đó.
- Trong C# thì giao tiếp được đánh dấu bởi từ khóa interface.
- Trong giao tiếp thì các thuộc tính và các hành vi ko được thực hiện (ko có code thực hiện).
- Một lớp trong C# có thể kế thừa nhiều giao tiếp.

10. Không gian tên (namespace)

- Namespace là một phần tử trong chương trình C# cho phép tổ chức các lớp, các giao tiếp, các cấu trúc.
- Namespace giúp cho việc tránh sự xung đột giữa các lớp, các giao tiếp, các cấu trúc (tránh sự trùng lặp tên) trong C#.
- Namespace giúp cho việc cấu trúc các thư viện, tổ chức nó thành dạng có thứ bậc (phân cấp) dễ dàng cho việc quản lý các lớp, các giao tiếp và các cấu trúc trong chương trình C#.
- Các namespace có thể lồng nhau (một namespace có thể nằm trong một namespace khác).
- Khi chúng ta tạo một Project trong VS.NET 2005 thì nó luôn tạo cho chúng ta một namespace mặc định có tên trùng với tên Project cho tất cả các cấu trúc, các lớp, các giao tiếp.
- Một namespace được khai báo bởi từ khóa namespace.
Cú pháp tổng quát để khai báo namespace:
namespace [tên của namespace]
{
[danh sách các lớp, các giao tiếp, các cấu trúc];
}
- Các namespace ko có bổ từ truy cập, mặc định bổ từ truy cập của các namespace luôn là public.
- Nếu trong Project chúng ta ko khai báo namespace cho các lớp thì các lớp đó thuộc về namespace mặc định (default namespace).
- Để thay đổi namespace mặc định của Project chúng ta click phải chuột vào Project chọn Properties sau đó gõ tên namespace mặc định cho Project ở mục Default Namespace.
- Qui ước cho việc đặt tên namespace (ko bắt buộc):
Tên namespace bao gồm 3 phần cách nhau bởi dấu chấm (.)
[Tên tổ chức].[tên ứng dụng].[tên module]
VD: đặt tên cho một ứng dụng quản lý nhân sự ở Aptech.
Aptech.EMS.Entities
Aptech.EMS.DAL
- Namespace là một cách tổ chức logic các lớp.
- Sử dụng namespace như thế nào?
Khi chúng ta muốn sử dụng các lớp, các cấu trúc, các giao tiếp trong một namespace thì chúng ta có 3 cách:

* Gõ tên đầy đủ của namespace chứa lớp và tên lớp. VD: để sử dụng lớp Employee trong namespace Aptech.EMS.Entities thì chúng ta sử dụng như sau:

Aptech.EMS.Entities.Employee.
Cách sử dụng như trên được gọi là fully qualified name.

* Sử dụng từ khóa using để khai báo namespace chứa thư viện các lớp, các giao tiếp, các cấu trúc.

VD: để sử dụng lớp Employee trong namespace Aptech.EMS.DAL chúng ta sử dụng:
using Aptech.EMS.DAL;
Employee e1 = new Employee();
Cách thứ hai được gọi là unqualified name.

* Sử dụng bí danh cùng với từ khóa using. using dal = Aptech.EMS.DAL;

using ent = Aptech.EMS.Entities;
dal.Employee e2 = new dal.Employee();
ent.Employee e3 = new ent.Employee();
- Tập hợp thư viện lớp của .NET Framework cũng được Microsoft tổ chức thành các namespace. VD: chúng ta có một số namespace cơ bản như sau:

* System: là namespace chứa các lớp thao tác với hệ thống.
* System.IO: là namespace chức các lớp thực hiện thao tác vào ra dữ liệu trên tệp tin.
* System.Windows.Form: là namespace chứa các lớp cho phép tạo và quản lý các cửa sổ trong ứng dụng Window Form.
* System.Data: là namespace chứa các lớp thực hiện thao tác với dữ liệu.
* System.Diagnostics: chứa các lớp cho phép thực hiện theo dõi và chuẩn đoán lỗi của ứng dụng.
* ……..

11. Xử lý ngoại lệ (Exception Handling)
- Exception (ngoại lệ): là bất kì sự bất thường nào xảy ra ko mong muốn trong ứng dụng.
- Một ứng dụng tốt thì cần phải giải quyết được tất cả các ngoại lệ có thể xảy ra.
- Các kiểu ngoại lệ: có 2 kiểu ngoại lệ trong C#.

* Các ngoại lệ ở mức hệ thống: các ngoại lệ này là những ngoại lệ được quăng ra (thrown) bởi hệ thống và thường là các nguyên nhân do hệ thống gây ra VD như thiếu bộ nhớ, kết nối mạng bị ngắt, phần cứng bị lỗi….
* Các ngoại lệ mức ứng dụng: là các ngoại lệ được quăng ra bởi người viết ứng dụng.

- Tất cả các ngoại lệ trong C# đều trực tiếp hoặc gián tiếp kế thừa từ một lớp là Exception. Lớp này nằm trong namespace System.
- Lớp Exception có các thuộc tính sau:

* Message: Lưu trữ thông điệp chỉ ra nguyên nhân của ngoại lệ.
* Source: chỉ ra tên của ứng dụng hoặc tên của đối tượng gây ra ngoại lệ.
* StackTrace: cung cấp thông tin chi tiết về ngoại lệ trên Stack vào thời điểm mà nó được quẳng ra.
* InnerException: trả về thể hiện của ngoại lệ gây ra ngoại lệ hiện tại.

- Cú pháp tổng quát để bắt ngoại lệ:
try
{
    [đoạn lệnh mà có khả năng xảy ra ngoại lệ];
}
catch ([kiểu ngoại lệ] [tên đối tượng ngoại lệ])
{
    [đoạn lệnh để xử lý ngoại lệ];
}
finally
{
    [đoạn lệnh được thực hiện cả trong 2 trường hợp xảy ra hoặc ko xảy ra ngoại lệ];
}
- Một try có thể có nhiều catch.
- Một ngoại lệ có thể được quăng ra bởi từ khóa throw.
- Để tạo ra một ngoại lệ thì chúng ta phải tạo ra một lớp kế thừa từ lớp Exception.

12. Delegate (chuyển giao)
- Delegate (chuyển giao): chuyển giao là các đối tượng chứa các tham chiếu đến các phương thức thay vì chứa tên phương thức thực tế. Chuyển giao trong C# giống với con trỏ hàm trong C.
- Chuyển giao là một đối tượng cho phép chúng ta thực hiện một cuộc gọi phương thức bất kì vào thời điểm mà chương trình đang thực hiện (runtime). Hình thức này được gọi dynamic calling.
- Để thực hiện khai báo một chuyển giao chúng ta sử dụng từ khóa delegate. Một delegate là một đối tượng tham chiếu đến một phương thức chính vì vậy khi khai báo delegate là chúng ta thực hiện khai báo khuôn dạng của phương thức mà delegate tham chiếu đến.
- Cú pháp khai báo 1 delegate:
[bổ từ truy cập] delegate [tên delegate] (danh sách các tham số);
VD: khai báo một delegate cho phép tham chiếu đến tất cả các hàm có 2 đối số nguyên và trả về một số nguyên.
public delegate int PhepTinhDelegate (int a, int b);
13. Event (sự kiện)
- Sự kiện: là một tín hiệu được thông báo giữa các đối tượng. Sự kiện xảy ra khi có sự tương tác giữa các đối tượng trong hệ thống. Sự kiện là các kích thích xảy ra bên trong hoặc bên ngoài hệ thống.
- Các bước tạo và sử dụng sự kiện trong C#.
Để tạo sự kiện trong C# thì đầu tiên chúng ta phải tạo một delegate để cho phép tham chiếu đến các phương thức mà thực hiện tương tác lại các sự kiện (đáp ứng khi các sự kiện xảy ra).
// Khai bao delegate.
public delegate void ViecMoiDelegate(string viec);
Khai báo sự kiện: sử dụng từ khóa event.
Cú pháp tổng quát:
[bổ từ truy cập] event [tên delegate] [tên sự kiện];
VD:
public event ViecMoiDelegate OnViecLamMoi = null;
Khai báo hàm được sử dụng để phát ra sự kiện:
public void ThongBao(string viec)
{
    // Kiem tra xem su kien da duoc dang ky chua neu dang ky roi thi phat ra su kien
    // do.
    if (OnViecLamMoi != null)
        OnViecLamMoi(viec);
}
Các đối tượng đăng ký sự kiện (các đối tượng này được gọi là subcribers).
Để đăng ký sự kiện chúng ta sử dụng cú pháp += như sau:
// 4. Dang ky nhan su kien cua cong ty moi gioi.
ctyMoiGioi.OnViecLamMoi += new ViecMoiDelegate(NhanThongBao);
Phát ra sự kiện:
ctyA.ThongBao("Ki su phan mem tai cty B");

[Programming in C#] Bài 5: Mảng và các lớp, phương thức trong C#

1. Mảng (Array)
a. Giới thiệu về mảng

- Trong chương trình đôi khi chúng ta cần thực hiện lưu trữ một loạt các thông tin có cùng kiểu dữ liệu để làm điều này thường chúng ta sẽ phải khai báo rất nhiều biến tương ứng với mỗi một thông tin như vậy. Việc quản lý số lượng lớn các biến gây ra rất nhiều khó khăn. Để giải quyết các khó khăn này thì C# cũng như các ngôn ngữ lập trình khác cung cấp một kiểu cấu trúc dữ liệu cho phép quản lý các biến có cùng tên, cùng kiểu dữ liệu. Đó là mảng.
- Mảng là một tập hợp hữu hạn các phần tử có cùng kiểu dữ liệu. Có thể coi mảng là một cách quản lý danh sách các biến có cùng kiểu dữ liệu.
- Để khai báo mảng trong C# chúng ta sử dụng cú pháp:
[Kiểu dữ liệu] [ ] … [ ] [tên mảng];
Trong đó:
[Kiểu dữ liệu]: là bất kì một kiểu dữ liệu nào được hỗ trợ trong C#.
[Tên mảng]: là một định danh để phân biệt các mảng với các biến, các đối tượng khác.
Số lượng các cặp dấu [ ] : chỉ ra chiều của mảng.
Nếu có 1 dấu [ ] thì mảng là mảng 1 chiều.
Nếu có 2 dấu [ ] thì mảng là mảng 2 chiều.
Nếu có 3 dấu [ ] thì mảng là mảng 3 chiều.
……………….
Nếu có n dấu [ ] thì mảng là mảng n chiều.
VD: khai báo mảng 1 chiều lưu trữ phần tử nguyên có tên là x.

int[] x;
- Khởi tạo mảng: là quá trình khai báo số lượng các phần tử của mảng và gán giá trị cho các phần tử đó.
Để khởi tạo mảng trong C# chúng ta có các cách như sau:

* Khai báo và chỉ ra số phần tử của mảng.

Cú pháp:
[Kiểu dữ liệu] [ ] [tên mảng] = new [Kiểu dữ liệu] [số lượng phần tử];
VD: khai báo một mảng số nguyên lưu trữ 20 phần tử.
int[] x = new int[20];
* Khai báo sau đó mới khởi tạo số phần tử của mảng.

[Kiểu dữ liệu] [ ] [tên mảng];
[tên mảng] = new [kiểu dữ liệu] [số phần tử];
VD: khai báo một mảng số nguyên lưu trữ 20 phần tử.
int[] x;
x = new int[20];
* Khai báo, chỉ ra số lượng các phần tử mảng và gán các giá trị ban đầu cho các phần tử mảng.
int[] x = new int[5] { 5, -7, 8, 1, 9 };

* Khai báo, ko chỉ ra số lượng các phần tử mảng và gán giá trị cho các phần tử của mảng.

- Truy cập các phần tử mảng: một mảng là một danh sách các phần tử có cùng kiểu dữ liệu, các phần tử đó được đánh số thứ tự bắt đầu từ 0 đến n-1 (Trong đó n là số phần tử của mảng).
Như vậy để truy cập đến 1 phần tử của mảng thì chúng ta sử dụng một số nguyên để chỉ ra số thứ tự của phần tử đó trong mảng, phần tử nguyên này được gọi là chỉ số (index).
Cú pháp tổng quát để truy cập đến phần tử thứ i của mảng là:
[tên mảng] [i-1];
VD: gán giá trị -9 cho phần tử thứ 3 của mảng.
x[2] = -9;
- Duyệt qua các phần tử mảng.
Kể từ khi mảng là một tập hợp các hữu hạn phần tử do đó để duyệt qua các phần tử mảng thường chúng ta sử dụng vòng lặp for.
VD: in danh sách các phần tử mảng x ở trên.
Console.WriteLine("Danh sach cac phan tu trong mang:");
for (int i = 0; i < 5; i++)
    Console.Write(x[i] + "\t");
b. Các kiểu mảng
Có 3 kiểu mảng trong C#:
- Mảng 1 chiều (single-dimension array): mảng 1 chiều là một mảng các phần tử. Mảng 1 chiều được khai báo chỉ bao gồm 1 cặp dấu [ ].
- Mảng nhiều chiều (multi-dimension array): mảng nhiều chiều là mảng có số chiều từ 2 trở lên (có từ 2 cặp [ ] trở lên).
VD về sử dụng mảng 2 chiều: mảng 2 chiều thường được sử dụng để lưu trữ các thông tin dạng bảng. VD: lưu trữ bảng điểm của 1 sinh viên.
Một sinh viên có nhiều môn học (tối đa 5 môn học), mỗi môn học có thể có nhiều điểm số (VD: tối đa là 3 điểm).
Để lưu trữ thông tin này chúng ta dùng mảng 2 chiều như sau:
// Khai báo một mảng 2 chiều 5 dòng và 3 cột để lưu
// trữ danh sách bảng điểm của 1 sinh viên.
float[,] diem = new float[5, 3];

// Nhập danh sách điểm cho sinh viên.
Console.WriteLine("Nhap diem cho sinh vien");
for (int i = 0; i < 5; i++)
{
    Console.WriteLine("Nhap diem cho mon thu {0}", i + 1);
    for (int j = 0; j < 3; j++)
    {
        Console.Write("Nhap diem thu {0}: ", j + 1);
        diem[i, j] = float.Parse(Console.ReadLine());
    }
}
// In danh sách điểm cho sinh viên trên dạng bảng.
Console.WriteLine("\n\tDiem1\tDiem2\tDiem3\n");
for (int i = 0; i < 5; i++)
{
    Console.Write("Mon{0}\t", i + 1);
    for (int j = 0; j < 3; j++)
        Console.Write(diem[i, j] + "\t");
    Console.WriteLine();
}

- Mảng nhọn (jagged array): mảng nhọn là một mảng của các mảng, trong đó kích thước của mỗi một mảng có thể khác nhau. Mảng nhọn cho phép chúng ta sử dụng bộ nhớ một cách tiết kiệm hơn.
VD: về việc sử dụng mảng nhọn áp dụng cho trường hợp dùng mảng để lưu trữ danh sách điểm của một sinh viên (một sinh viên có tối đa 5 môn học) và mỗi môn học có thể có một hoặc nhiều điểm.
// Khai báo mảng jagged.
float[][] diem = new float[5][] {new float[] {9},
new float[] {1,4,4,6},
new float[] {3,3,5},
new float[] {2,7},
new float[] {10}};

// Duyệt qua các phần tử của mảng jagged.
for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < diem[i].Length; j++)
        Console.Write(diem[i][j] + "\t");
    Console.WriteLine();
}

Console.ReadLine();
c. Lớp mảng
- Trong C# thì tất cả mọi thứ đều là đối tượng.
- Như vậy mảng cũng là một đối tượng.
- Để hỗ trợ cho việc thao tác với các mảng thì C# cung cấp cho chúng ta một lớp mà có các phương thức, các thuộc tính để chúng ta sử dụng và thao tác với mảng.
- Lớp này có tên là Array nằm trong namespace có tên System.
- Lớp này cung cấp các phương thức tĩnh để chúng ta có thể thực hiện một số các thao tác cơ bản trên mảng như:

* Sắp xếp: Sort.
* Tìm kiếm: IndexOf (hàm này thực hiện tìm kiếm một phần tử x trong mảng y, hàm trả về -1 nếu ko tìm thấy x trong mảng y và trả về vị trí của phần tử x trong mảng y nếu tìm thấy).
* Đảo ngược các phần tử: Reverse.

[Programming in C#] Bài 4: Các cấu trúc lập trình trong C#

1. Các cấu trúc lựa chọn (Selection Constructs)
- Cấu trúc lựa chọn là một cấu trúc lập trình được hỗ trợ bởi C# để cho phép điều khiển luồng thực hiện c���a chương trình.
- Các cấu trúc lựa chọn hoạt động trên cơ sở một điều kiện. Do vậy các cấu trúc lựa chọn còn được gọi với một tên khác là cấu trúc điều kiện.
- Có 4 kiểu cấu trúc lựa chọn trong C#:

Cấu trúc if … else:

Cú pháp:

if (điều kiện)
[khối lệnh 1];
else
[khối lệnh 2];
Trong đó:
Điều kiện: là một biểu thức logic (trả về giá trị true hoặc false).


Khối lệnh: là một hoặc nhiều câu lệnh, mỗi khối lệnh bắt đầu và kết thúc với { }
Cấu trúc này sẽ thực hiện kiểm tra Điều kiện nếu điều kiện đúng thì Khối lệnh 1 được thực hiện và nếu sai thì Khối lệnh 2 được thực hiện.
VD: viết đoạn code thực hiện giải PT bậc nhất.

float a, b, x;

Console.WriteLine("Chuong trinh giai PT bac nhat: ax + b = 0");
Console.Write("a = ");
a = float.Parse(Console.ReadLine());
Console.Write("b = ");
b = float.Parse(Console.ReadLine());

if (a == 0)
    Console.WriteLine("PT hien tai dang xem xet");
else
    Console.WriteLine("PT co nghiem: x = {0}", -b / a);

Console.ReadLine();

Cấu trúc if … else if: trong trường hợp chúng ta muốn chương trình có thể thực hiện theo nhiều luồng thì chúng ta sẽ dùng đến cấu trúc if … else if.

Cú pháp tổng quát:

if (điều kiện 1)
[khối lệnh 1];
else if (điều kiện 2)
[khối lệnh 2];
......
else if (điều kiện i);
[khối lệnh i];


......
else
[khối lệnh n];


Chương trình sẽ thực hiện kiểm tra Điều kiện 1, nếu điều kiện 1 đúng thì khối lệnh 1 được thực hiện nếu sai thì kiểm tra điều kiện 2, nếu điều kiện 2 đúng thì khối lệnh 2 được thực hiện, nếu sai thì điều kiện 3 được kiểm tra…
VD: viết chương trình cho phép nhập điểm số của 1 sinh viên. Thực hiện xếp loại sinh viên đó biết rằng:

        * Nếu điểm số <5 -> loại yếu.
        * Nếu điểm số >=5 và <6.5 -> loại trung bình.
        * Nếu điểm số >=6.5 và <7.5 -> loại khá.
        * Nếu điểm số >=7.5 và <=8.5 -> loại giỏi.
        * Nếu điểm số >=8.5 -> loại xuất sắc.

 

 

float diemSo;
Console.Write("Nhap diem: ");
diemSo = float.Parse(Console.ReadLine());
if (diemSo < 5)
    Console.WriteLine("Xep loai yeu");
else if (diemSo < 6.5)
    Console.WriteLine("Xep loai trung binh");
else if (diemSo < 7.5)
    Console.WriteLine("Xep loai kha");
else if (diemSo < 8.5)
    Console.WriteLine("Xep loai gioi");
else
    Console.WriteLine("Xep loai xuat sac");
Console.ReadLine();

Cấu trúc if lồng nhau: một lệnh if mà nằm trong 1 lệnh if khác thì lệnh if đó được gọi là if lồng.

VD: giải PT bậc nhất đầy đủ.

float a, b;

Console.WriteLine("Chuong trinh giai PT bac nhat: ax + b = 0");
Console.Write("a = ");
a = float.Parse(Console.ReadLine());
Console.Write("b = ");
b = float.Parse(Console.ReadLine());

if (a == 0)
{
    if (b == 0)
        Console.WriteLine("PT vo so nghiem");
    else
        Console.WriteLine("PT vo nghiem");
}
else
    Console.WriteLine("PT co nghiem: x = {0}", -b / a);

Console.ReadLine();

Cấu trúc đa nhánh switch … case: cấu trúc này cho phép chúng ta thực hiện điều khiển luồng thực hiện của chương trình theo nhiều luồng khác nhau dựa vào giá trị của một biểu thức (là biểu thức đếm được).

Cú pháp:

switch (biểu thức)
{
case [giá trị 1]:
[lệnh 1];
break;
case [giá trị 2]:
[lệnh 2];
break;
case [giá trị 3]:
[lệnh 3];
break;
..................
case [giá trị n]:
[lệnh n];
break;
default:
[lệnh n+1];
}


Lệnh này sẽ đánh giá giá trị của Biểu thức.
Nếu biểu thức có giá trị bằng giá trị 1 thì lệnh 1 sẽ được thực hiện.
Nếu biểu thức có giá trị bằng giá trị 2 thì lệnh 2 sẽ được thực hiện.
…………………..
Nếu biểu thức có giá trị bằng giá trị n thì lệnh n sẽ được thực hiện.
Ngược lại nếu giá trị biểu thức khác tất cả các giá trị trên thì lệnh n+1 được thực hiện.

CHÚ Ý: biểu thức phải là một biểu thức có giá trị đếm được có nghĩa là kiểu dữ liệu của biểu thức phải là số nguyên hoặc kí tự hoặc chuỗi kí tự hoặc kiểu dữ liệu liệt kê (enum).
VD: viết chương trình xác định xem ngày nào đó là thứ mấy biết ngày hiện tại 16/04/2010 là thứ 6.
string ngayNhap;

 

Console.Write("Nhap ngay muon xem (ngay/thang/nam): ");
ngayNhap = Console.ReadLine();
DateTime ngay = DateTime.Parse(ngayNhap);
DateTime ngay16042010 = new DateTime(2010, 4, 16);
int kc = Math.Abs(ngay16042010.Day - ngay.Day);
switch (kc % 7)
{
    case 0:
        Console.Write("Ngay nay la thu sau");
        break;
    case 1:
        Console.Write("Ngay nay la thu bay");
        break;
    case 2:
        Console.Write("Ngay nay la chu nhat");
        break;
    case 3:
        Console.Write("Ngay nay la thu hai");
        break;
    case 4:
        Console.Write("Ngay nay la thu ba");
        break;
    case 5:
        Console.Write("Ngay nay la thu tu");
        break;
    case 6:
        Console.Write("Ngay nay la thu nam");
        break;
}
Console.ReadLine();

2. Các cấu trúc lặp (Loop Constructs)
- Cấu trúc lặp là một cấu trúc cho phép chúng ta thực hiện một đoạn code lặp đi lặp lại cho đến khi thỏa mãn một điều kiện nào đó.
- Có 4 cấu trúc lặp được sử dụng trong C#:

Cấu trúc lặp while:

Cú pháp:

while (điều kiện)
{
[khối lệnh];
}


Trong đó:
điều kiện là một biểu thức logic.
Vòng lặp này sẽ thực hiện kiểm tra điều kiện trước. Nếu điều kiện đúng thì thực hiện khối lệnh sau đó quay lại kiểm tra điều kiện. Công việc này sẽ được thực hiện liên tục cho đến khi điều kiện có giá trị sai.
VD: bài toán một người có số tiền m gửi vào ngân hàng A với lãi suất gửi là x%/1 tháng. Hỏi sau bao nhiêu tháng thì người này sẽ được số tiền là n.

 

float m, n, x;
int soThang = 0;
Console.Write("So tien gui: ");
m = float.Parse(Console.ReadLine());
Console.Write("So tien muon co: ");
n = float.Parse(Console.ReadLine());
Console.Write("Lai xuat (%/1 thang): ");
x = float.Parse(Console.ReadLine());
while (m < n)
{
    m = m + (float)(m * x / 100);
    soThang++;
}
Console.WriteLine("So thang phai gui la: {0}", soThang);
Console.ReadLine();

Cấu trúc do … while:

Cú pháp:

do
{
[khối lệnh];
}
while (điều kiện);


Câu lệnh này sẽ thực hiện khối lệnh sau đó kiểm tra điều kiện, nếu điều kiện sai thì kết thúc vòng lặp, nếu điều kiện đúng thì thực hiện tiếp khối lệnh sau đó lại kiểm tra điều kiện.
VD: viết chương trình tính tổng của 2 số, lặp lại việc đó cho đến khi người dùng trả lời ko muốn tiếp tục nữa.

 

int a, b;
char traLoi;
do
{
    Console.Write("a = ");
    a = int.Parse(Console.ReadLine());

    Console.Write("b = ");
    b = int.Parse(Console.ReadLine());

    Console.WriteLine("Tong 2 so: {0}", a + b);
    Console.Write("Ban co tiep tuc ko (C/K)?");
    do
    {
        ConsoleKeyInfo key = Console.ReadKey();
        traLoi = key.KeyChar;
    }
    while (!(traLoi == 'c' || traLoi == 'C' || traLoi == 'k' || traLoi == 'K'));
    Console.WriteLine();
}
while (traLoi == 'c' || traLoi == 'C');

Cấu trúc lặp for:

Cấu trúc lặp for thường được sử dụng trong trường hợp biết trước số lần lặp.
Cú pháp:

for ([biểu thức khởi tạo]; [biểu thức kiểm tra điều kiện]; [biểu thức thay đổi giá trị vòng lặp])
[khối lệnh];


Trong đó:
[biểu thức khởi tạo]: là danh sách các lệnh thực hiện khởi tạo giá trị cho các biến trong vòng lặp, các lệnh này cách nhau bởi dấu phẩy (,).
[biểu thức kiểm tra điều kiện]: là biểu thức được sử dụng để kiểm tra điều kiện dừng của vòng lặp. Nếu điều kiện đúng thì vòng lặp tiếp tục được thực hiện, nếu sai thì kết thúc vòng lặp.
[biểu thức thay đổi giá trị vòng lặp]: là biểu thức thực hiện thay đổi các giá trị của các biến được sử dụng để điều khiển vòng lặp.
VD: viết chương trình in ra tổng các cặp số chẵn nhỏ hơn 300.

 

for (int i = 2, j = 2; i + j < 300; i += 2, j += 2)
{
    Console.WriteLine("{0} + {1} = {2}", i, j, i + j);
}

Console.ReadLine();

Cấu trúc lặp foreach: cấu trúc lặp này được sử dụng để cho phép duyệt qua một tập hợp và thực hiện lặp đi lặp lại cho đến cuối của tập hợp đó.

Cú pháp:

foreach ([kiểu đối tượng] [tên đối tượng] in [tên tập hợp])
[khối lệnh];


Vòng lặp này sẽ thực hiện khối lệnh với mỗi một đối tượng nằm trong tập hợp.
VD: Sinh ra một tập hợp ngẫu nhiên các số nguyên trong khoảng [0..100] sau đó in ra tất cả các phần tử trong tập hợp đó.

 

ArrayList arr = new ArrayList();

// Phát sinh số n ngẫu nhiên trong khoảng từ [5,15].
Random rnd = new Random();
int n = 5 + rnd.Next(10);

// Phát sinh ra n số ngẫu nhiên trong khoảng từ [0..100].
for (int i = 1; i <= n; i++)
    arr.Add(rnd.Next(100));

// In ra các số trong tập hợp arr trên sử dụng vòng lặp foreach.
Console.WriteLine("Mang ngau nhien duoc sinh ra la: ");
foreach (int x in arr)
{
    Console.Write(x + " ");
}

Console.ReadLine();

3. Các lệnh nhảy (Jump Statements)
- Các lệnh nhẩy là những lệnh cho phép thay đổi (chuyển điều khiển) từ một vị trí này đến một vị trí khác trong chương trình.
- Có 4 lệnh nhẩy cơ bản trong C#:

Lệnh break: lệnh này được sử dụng để kết thúc một vòng lặp hoặc một đoạn lệnh trong câu lệnh switch … case.

VD: viết chương trình cho phép in ra các số chia hết cho 3 trong khoảng từ 1 đến 100. Nếu có một số vừa chia hết cho 3 vừa chia hết cho 7 thì dừng.

for (int i = 1; i <= 100; i++)
{
    if (i % 3 == 0)
    {
        if (i % 7 == 0) break;
        Console.Write(i + " ");
    }
}



Lệnh continue: lệnh này cho phép nhảy đến lần lặp tiếp theo trong vòng lặp.

VD: viết chương trình thực hiện in ra danh sách các số từ 1 đến 100 bỏ qua các số chia hết cho 7.

for (int i = 1; i <= 100; i++)
{
    if (i % 7 == 0) continue;
    Console.Write(i + " ");
}


Lệnh goto: lệnh này cho phép chuyển đến một vị trí được định sẵn (được gán nhãn) trong chương trình.

VD: viết chương trình giải PT bậc nhất, lặp đi lặp lại cho đến khi trả lời ko tiếp tục nữa.

int a, b;
Console.WriteLine("Chuong trinh giai PT bac nhat");
BatDau:
Console.Write("a = ");
a = int.Parse(Console.ReadLine());
Console.Write("b = ");
b = int.Parse(Console.ReadLine());

if (a == 0)
    if (b == 0)
        Console.WriteLine("PT vo so nghiem");
    else
        Console.WriteLine("PT vo nghiem");
else
    Console.WriteLine("PT co 1 nghiem: x = {0}", (float)-b / a);

Console.Write("Ban co tiep tuc (C/K)?");
string traLoi = Console.ReadLine();
traLoi = traLoi.ToUpper();

if (traLoi.Equals("C")) goto BatDau;

Lệnh return: lệnh return dùng để kết thúc một hàm và trả về kết quả cho hàm đó.

 

[Programming in C#] Bài 3: Các lệnh và toán tử trong C#

1. Vào ra dữ liệu trong C# (trong môi trường Console)
- C# hỗ trợ vào ra dữ li���u trong môi trường Console thông qua đối tượng Console. Đối tượng này nằm trong thư viện (namespace) có tên: System.
- Để khai báo thư viện sử dụng dòng lệnh:

using System;
- Để xuất dữ liệu (ra – output) chúng ta sử dụng 2 phương thức:

* Write: phương thức này cho phép in dữ liệu ra màn hình Console theo định dạng. Dữ liệu có thể là các hằng số, các biến, các biểu thức.

Có tất cả 18 quá tải phương thức (overloadding method) để cho phép chúng ta có thể thực hiện in ra giá trị của các kiểu hằng số, biến khác nhau.

Trong đó có hàm tổng và thường được sử dụng nhất là:

Cú pháp:
Console.Write(“chuỗi định dạng”,”danh sách các đối số”);
Trong đó:
“Chuỗi định dạng”: là chuỗi kí tự chỉ ra dạng hiển thị (trình bày của dữ liệu).
Chuỗi định dạng có thể là:

* Các kí tự: kí tự số (0,2,3,4….9) hoặc các kí tự chữ ‘a’, ‘z’,’A’,’X’….’%’.
* Các kí tự thoát (escape sequence): các kí tự thoát bắt đầu với dấu % hoặc dấu \. VD: kí tự điều khiển xuống dòng là \n hoặc kí tự điều khiển nhẩy 1 Tab là \t.
* Kí tự giữ chỗ (placeholder): các kí tự giữ chỗ này có dạng {n}. Trong đó n là số nguyên chỉ ra số thứ tự của đối số.

“danh sách các đối số”: là danh sách các biến hoặc các hằng số hoặc các biểu thức cách nhau bởi dấu phẩy (,). VD: -7, ‘a’, (a+b)*c, x…

VD: sử dụng lệnh Write để in ra giá trị tương ứng của các biến a, b, c và giá trị của biểu thức (a+b)*c.

int a, b, c;

a = 3;
b = -5;
c = 9;

Console.Write("a = {0}, b = {1}, c = {2}, fx = {3}",a,b,c,(a+b)*c);

Chú ý:

* Số lượng các placeholder trong chuỗi định dạng bằng với số lượng các đối số trong danh sách các đối số.
* Giá trị số của các placeholder bắt đầu được đánh số thứ tự từ 0.
* Thứ tự của các đối số sẽ tương ứng với thứ tự của các placeholder.

* WriteLine: hàm thực hiện in dữ liệu và chuyển con trỏ đến dòng tiếp theo trên màn hình Console.

- Hàm nhập dữ liệu (input): để nhập dữ liệu cho ứng dụng Console chúng ta có thể sử dụng các hàm sau:

* Read: hàm read cho phép đọc 1 số nguyên từ vùng đệm bàn phím trong ứng dụng Console. Hàm này trả về 1 số nguyên.
* ReadKey: hàm này cho phép đọc 1 phím từ bàn phím.
* ReadLine: hàm này cho phép nhập 1 chuỗi kí tự.

Một số hàm liên quan đến quá trình nhập liệu khác:

* Parse: hàm này thực hiện phân tích và chuyển đổi 1 kiểu dữ liệu thành một kiểu dữ liệu khác.

VD1: để chuyển 1 chuỗi kí tự thành 1 số nguyên thì dùng dòng lệnh.

int a;
a = int.Parse(Console.ReadLine());

VD2: để chuyển 1 chuỗi kí tự thành 1 số thực decimal thì dùng dòng lệnh.

decimal n;
n = decimal.Parse(Console.ReadLine());

* Đối tượng Convert: là đối tượng cho phép biến đổi 1 kiểu dữ liệu bất kì thành 1 kiểu dữ liệu khác. Đối tượng này chứa các phương thức tĩnh tương ứng cho việc chuyển đổi các kiểu dữ liệu dữ liệu sang một kiểu dữ liệu nào đó. VD: để chuyển đổi sang số nguyên chúng ta có thể dùng các hàm ToInt16, ToInt32, ToInt64, chuyển sang số thực dùng các hàm ToFloat, ToDouble, ToDecimal…

VD:

a = Convert.ToInt32(Console.ReadLine());

2. Lệnh và các biểu thức
- Định nghĩa: lệnh là một nhóm logic các biến, các toán tử và các từ khóa để thực hiện 1 công việc cụ thể nào đó.
VD: lệnh để khai báo 1 hằng số thực PI có giá trị bằng 3.14.
const float PI = 3.14f;
- Các lệnh trong C# đều kết thúc bởi dấu chấm phẩy (.
- Định nghĩa: khối lệnh (block) là một nhóm các câu lệnh thực hiện 1 nhiệm vụ cụ thể nào đó. Các khối lệnh nằm trong cặp dấu
VD: khối lệnh tính diện tích hình tròn.

float banKinh;
float dienTich;

Console.Write("Nhap ban kinh: ");
banKinh = float.Parse(Console.ReadLine());

dienTich = banKinh * banKinh * Math.PI;
Console.WriteLine("Dien tich: {0}", dienTich);

Console.ReadLine();


3. Các kiểu lệnh
Có 7 kiểu lệnh trong C#:
- Các lệnh lựa chọn (Selection Statements): là những lệnh tạo ra quyết định một đoạn mã lệnh nào đó có được thực hiện hay ko dựa vào một điều kiện. Một số lệnh thuộc nhóm này: if, switch.
- Các lệnh lặp (Iteration Statements): là cấu trúc lệnh giúp chúng ta thực hiện lặp đi lặp lại một đoạn mã lệnh cho đến khi thỏa mãn một điều kiện nào đó. Các lệnh thuộc nhóm này: for, foreach, do, while.
- Các lệnh nhảy (Jump Statements): là các lệnh giúp chúng ta chuyển luồng thực hiện của chương trình (flow of program) từ một đoạn mã lệnh này sang một đoạn mã lệnh khác. Các lệnh thuộc nhóm này: break, continue, return, goto, default, yield.
- Các lệnh xử lý ngoại lệ (Exception Handling Statements): là các lệnh được sử dụng để kiểm soát những tình huống ko mong muốn xảy ra trong ứng dụng của chúng ta và làm cho ứng dụng hoạt động sai hoặc bị phá vỡ. Các lệnh thuộc nhóm này: try, catch, finally, throw.
- Các lệnh được kiểm tra và ko được kiểm tra (Checked and UnChecked Statements): những lệnh ko được kiểm tra là những lệnh sẽ được bỏ qua bởi trình quản lý code (CLR) còn những lệnh được kiểm tra là những lệnh sẽ được kiểm soát bởi CLR. Và để chỉ ra những lệnh nào là được kiểm tra và ko được kiểm tra thì chúng ta sử dụng các từ khóa tương ứng là: checked và unchecked. Mặc định các lệnh đều thuộc nhóm checked.
- Các lệnh fixed: các lệnh fixed được sử dụng để chỉ ra cho GC (trình thu gom rác – Garbage Collector) là sẽ bỏ qua việc thu hồi bộ nhớ được sử dụng bởi các đối tượng trong đoạn lệnh fixed này. Các từ được sử dụng là: fixed và unsafe.
- Các lệnh khóa (Lock Statements): là các lệnh giúp cho việc khóa các đoạn code quan trọng để đảm bảo rằng các tiến trình (process) hoặc các tuyến đoạn (thread) khác có thể can thiệp vào bộ nhớ mà đang được sử dụng bởi đoạn lệnh nào đó. Các lệnh này được sử dụng để đảm bảo tính bảo mật và chỉ hoạt động trên các kiểu dữ liệu tham chiếu. Từ khóa được sử dụng là lock.

8. Các biểu thức

- Biểu thức (expression) là một sự kết hợp của các toán tử (operators) và các toán hạng (operands).
- Toán tử là một kí hiệu để chỉ ra thao tác trên dữ liệu. VD: + để chỉ ra thao tác tính tổng 2 số…
- Toán hạng có thể là các hằng số, các biến hoặc các hàm. VD: -7, x, Sin(PI/180)…
- Một số VD về biểu thức:
x+y
(x-y)/(x+y)
Sin(x*x)/2+5*y
- Để gán giá trị của một biểu thức vào một biến chúng ta sử dụng toán tử gán (assignment operator). Cú pháp:
[tên biến] = [biểu thức];

9. Các kiểu toán tử
Có 6 kiểu toán tử:
- Toán tử toán học (Arithmetic Operators): là các toán tử được sử dụng để thực hiện các thao tác tính toán toán học ví dụ như: tính tổng, hiểu, tích, thương, lấy phần dư….
Một số các toán tử toán học:
+ : tính tổng
- : tính hiệu
* : tính tích
/ : tính thương
% : lấy phần dư của phép chia a cho b
- : toán tử âm.
- Toán tử quan hệ (Relational Operators): là những toán tử được sử dụng để kiểm tra mối quan hệ giữa các toán hạng.
> : kiểm tra lớn hơn
< : kiểm tra nhỏ hơn
= = : kiểm tra bằng nhau
!= : kiểm tra khác nhau
>= : kiểm tra lớn hơn hoặc bằng
<= : kiểm tra nhỏ hơn hoặc bằng
- Toán tử logic (Logical Operators): là những toán tử được sử dụng để liên kết các toán hạng, các biểu thức với nhau.
&& : toán tử VÀ.
|| : toán tử HOẶC.
! : toán tử PHỦ ĐỊNH.
- Các toán tử trên bit (Bitwise Operators): là các toán tử thực hiện các thao tác logic trên bit.
& : và logic trên bit.
| : hoặc logic trên bit.
^ : toán tử lấy phần bù.
- Các toán tử tăng và giảm (Increment and Decrement Operators): các toán tử này được sử dụng để tăng hoặc giảm giá trị của biến.
-- : giảm giá trị của biến xuống 1 đơn vị.
++ : tăng giá trị của biến lên 1 đơn vị.
- Toán tử gán (Assignment Operator): được sử dụng để gán giá trị của một hằng số hoặc một biến hoặc 1 biểu thức cho một biến.
Toán tử gán sử dụng dấu =.

10. Chuyển đổi dữ liệu trong C#
- Trong quá trình xây dựng chương trình thì cần có sự chuyển đổi linh hoạt giữa các loại dữ liệu được sử dụng trong chương trình.
- Sự chuyển đổi này có 2 loại:
Chuyển đổi ngầm định (Implicit conversion): chuyển đổi ngầm định được sử dụng trong trường hợp chúng ta chuyển dữ liệu từ một kiểu dữ liệu có phạm vi lưu trữ thấp sang một kiểu dữ liệu có phạm vi lưu trữ lớn hơn.
VD: chuyển dữ liệu từ kiểu số nguyên sang kiểu số thực.

int x = -7;
float y = x; // implicit conversion.

Chuyển đổi ép buộc - rõ ràng (Explicit conversion): kiểu chuyển đổi được sử dụng trong trường hợp chúng ta muốn chuyển dữ liệu từ một kiểu dữ liệu có phạm vi lưu trữ lớn hơn về một kiểu dữ liệu có phạm vi lưu trữ nhỏ hơn.
VD: chuyển dữ liệu từ kiểu số thực về số nguyên.

float x1 = -3.76f;
int x2 = (int)x1; // explicit conversion.

- Một hình thức chuyển đổi kiểu dữ liệu khác đó là chuyển đổi dữ liệu từ kiểu dữ liệu tham trị sang kiểu dữ liệu tham chiếu và ngược lại.
Nếu chúng ta chuyển từ kiểu dữ liệu tham trị sang tham chiếu thì gọi là Boxing. Boxing ko sử dụng toán tử ép kiểu.
VD:

int n1 = -9; // value type.
object o1 = n1; // value type -> reference type: Boxing.

Nếu chúng ta chuyển kiểu dữ liệu từ kiểu tham chiếu sang kiểu tham trị thì gọi là UnBoxing. Để thực hiện UnBoxing thì phải ép kiểu.
VD:

int n1 = -9; // value type.
object o1 = n1; // value type -> reference type: Boxing.
int n2 = (int)o1; // reference type -> value type: UnBoxing.