Tải bản đầy đủ
1 Tổng quan về ngôn ngữ C sharp (C #)

1 Tổng quan về ngôn ngữ C sharp (C #)

Tải bản đầy đủ

trường .NET. Nó cũng là một ngôn ngữ hoàn toàn hướng đối tượng được thiết kế
dựa trên kinh nghiệm của các ngôn ngữ khác.
Trọng tâm của ngôn ngữ hướng đối tượng là lớp. Lớp định nghĩa kiểu dữ liệu
mới, cho phép mở rộng ngôn ngữ theo hướng cần giải quyết. C# có những từ
khóa dành cho việc khai báo lớp, phương thức, thuộc tính mới. C# hỗ trợ đầy đủ
khái niệm trụ cột trong lập trình hướng đối tượng: đóng gói, thừa kế, đa hình.
C# cũng hỗ trợ giao diện interface, nó được xem như một cam kết với một
lớp cho những dịch vụ mà giao diện quy định. Trong ngôn ngữ C#, một lớp chỉ
có thể kế thừa từ duy nhất một lớp cha, tức là không cho đa kế thừa như trong
ngôn ngữ C++, tuy nhiên một lớp có thể thực thi nhiều giao diện. Khi một lớp
thực thi một giao diện thì nó sẽ hứa là nó sẽ cung cấp chức năng thực thi giao
diện.
Trong ngôn ngữ C#, những cấu trúc cũng được hỗ trợ, nhưng khái niệm
về ngữ nghĩa của nó thay đổi khác với C++. Trong C#, một cấu trúc được giới
hạn, là kiểu dữ liệu nhỏ gọn, và khi tạo thể hiện thì nó yêu cầu ít hơn về hệ điều
hành và bộ nhớ so với một lớp. Một cấu trúc thì không thể kế thừa từ một lớp
hay được kế thừa nhưng một cấu trúc có thể thực thi một giao diện.
Ngôn ngữ C# cung cấp những đặc tính hướng thành phần (componentoriented), như là những thuộc tính, những sự kiện. Lập trình hướng thành phần
được hỗ trợ bởi CLR cho phép lưu trữ metadata với mã nguồn cho một lớp.
Metadata mô tả cho một lớp, bao gồm những phương thức và những thuộc tính
của nó, cũng như những sự bảo mật cần thiết và những thuộc tính khác. Mã
nguồn chứa đựng những logic cần thiết để thực hiện những chức năng của nó..
Do vậy, một lớp được biên dịch như là một khối self-contained, nên môi trường
hosting biết được cách đọc metadata của một lớp và mã nguồn cần thiết mà
không cần những thông tin khác để sử dụng nó.
C# là ngôn ngữ này cũng hỗ trợ việc truy cập bộ nhớ trực tiếp sử dụng kiểu
con trỏ của C++ và từ khóa cho dấu ngoặc [] trong toán tử. Các mã nguồn này là
không an toàn (unsafe). Và bộ giải phóng bộ nhớ tự động của CLR sẽ không thực

24

hiện việc giải phóng những đối tượng được tham chiếu bằng sử dụng con trỏ cho
đến khi chúng được giải phóng.
2.1.2 Nền tảng ngôn ngữ C#
2.1.2.1 Kiểu dữ liệu
Điều cốt lõi của lập trình hướng đối tượng là tạo ra các kiểu mới. Kiểu là
một thứ được xem như trừu tượng. Nó có thể là một bảng dữ liệu, một tiểu trình,
hay một nút lệnh trong một cửa sổ. Tóm lại kiểu được định nghĩa như một dạng
vừa có thuộc tính chung (properties) và các hành vi ứng xử (behavior) của nó
C# là ngôn ngữ lập trình mạnh về kiểu dữ liệu, một ngôn ngữ mạnh về
kiểu dữ liệu là phải khai báo kiểu của mỗi đối tượng khi tạo (kiểu số nguyên, số
thực, kiểu chuỗi, kiểu điều khiển...) và trình biên dịch sẽ giúp cho người lập trình
không bị lỗi khi chỉ cho phép một loại kiểu dữ liệu có thể được gán cho các kiểu
dữ liệu khác. Kiểu dữ liệu của một đối tượng là một tín hiệu để trình biên dịch
nhận biết kích thước của một đối tượng (kiểu int có kích thước là 4 byte) và khả
năng của nó (như một đối tượng button có thể vẽ, phản ứng khi nhấn,...).
Tương tự như C++ hay Java, C# chia thành hai tập hợp kiểu dữ liệu chính:
Kiểu xây dựng sẵn (built- in) mà ngôn ngữ cung cấp cho người lập trình và kiểu
được người dùng định nghĩa (user-defined) do người lập trình tạo ra.
C# phân tập hợp kiểu dữ liệu này thành hai loại: Kiểu dữ liệu giá trị
(value) và kiểu dữ liệu tham chiếu (reference). Việc phân chi này do sự khác
nhau khi lưu kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu trong bộ nhớ. Đối với
một kiểu dữ liệu giá trị thì sẽ được lưu giữ kích thước thật trong bộ nhớ đã cấp
phát là stack. Trong khi đó thì địa chỉ của kiểu dữ liệu tham chiếu thì được lưu
trong stack nhưng đối tượng thật sự thì lưu trong bộ nhớ heap.
Tất cả các kiểu dữ liệu xây dựng sẵn là kiểu dữ liệu giá trị ngoại trừ các đối
tượng và chuỗi. Và tất cả các kiểu do người dùng định nghĩa ngoại trừ kiểu cấu
trúc đều là kiểu dữ liệu tham chiếu.
Ngôn ngữ C# đưa ra các kiểu dữ liệu xây dựng sẵn rất hữu dụng, phù hợp
với một ngôn ngữ lập trình hiện đại, mỗi kiểu dữ liệu được ánh xạ đến một kiểu

25

dữ liệu được hỗ trợ bởi hệ thống xác nhận ngôn ngữ chung (Common Language
Specification: CLS) trong MS.NET.

Kiểu C#
Byte
Char
Bool
Sbyte
Short

Số byte
1
2
1
1
2

Kiểu .NET
Byte
Char
Boolean
Sbyte
Int16

Ushort
Int

2
4

Uint16
Int32

Uint
Float

4
4

Uint32
Single

Double

8

Double

decimal

8

Decime

Long

8

Int64

Ulong

8

Uint64

Mô tả
Số nguyên dương không dấu từ 0-255
Ký tự Unicode
Giá trị logic true/ false
Số nguyên có dấu ( từ -128 đến 127)
Số nguyên có dấu giá trị từ -32768 đến
32767.
Số nguyên không dấu 0 – 65.535
Số nguyên có dấu –2.147.483.647 và
2.147.483.647
Số nguyên không dấu 0 – 4.294.967.295
Kiểu dấu chấm động, giá trị xấp xỉ từ 3,4E38 đến 3,4E+38, với 7 chữ số có nghĩa
Kiểu dấu chấm động có độ chính xác gấp
đôi, giá trị xấp xỉ từ 1,7E-308 đến 1,7E+308,
với 15,16 chữ số có nghĩa.
Có độ chính xác đến 28 con số và giá trị thập
phân, được dùng trong tính toán tài chính,
kiểu này đòi hỏi phải có hậu tố “m” hay “M” theo
sau giá trị.
Kiểu số nguyên có dấu có giá trị trong
khoảng : -9.223.370.036.854.775.808 đến
9.223.372.036.854.775.807
Số nguyên không dấu từ 0 đến 0xffffffffffffffff
26

Bảng 3:Kiểu dữ liệu xây dựng sẵn
2.1.2.2 Biến, hằng và toán tử
a. Biến: Là một vùng lưu trữ ứng với một kiểu dữ liệu.

Biến có thể được gán giá trị và cũng có thể thay đổi giá trị trong khi thực
hiện các lệnh của chương trình.
Khai báo: [=];
b. Hằng: Hằng cũng là một biến nhưng giá tri của hằng không thay đổi trong

khi thực hiện các lệnh của chương trình. Hằng được phân thành 3 loại:
-

Giá trị hằng(literal)

-

Biểu tượng hằng(symbolic constants)

-

Kiểu liệt kê(enumerations)
Khai báo: =;
Hoặc:
{ =,
…………..
=;
}

c. Toán tử
-

Toán tử toán học: +,-,*,/,%

-

Toán tử tăng / giảm: +=,-=,*=,/=,%=

-

Toán tử tăng giảm 1 đơn vị: ++,--

-

Toán tử gán: =

-

Toán tử quan hệ: ==, !=, >, >=, <, <=

-

Toán tử logic: !, &&, ||

-

Toán tử 3 ngôi: (điều kiện)?(biểu_thức_1): (biểu_thức_2);
2.1.2.3 Câu lệnh
Trong C# một chỉ dẫn lập trình đầy đủ được gọi là câu lệnh. Chương trình

bao gồm nhiều câu lệnh tuần tự với nhau.

27

Có hai loại câu lệnh phân nhánh trong C# là : phân nhánh không có điều
kiện (unconditional branching statement) và phân nhánh có điều kiện
(conditional branching statement). Ngoài ra còn có các câu lệnh làm cho một số
đoạn chương trình được thực hiện nhiều lần, các câu lệnh này được gọi là câu
lệnh lặp hay vòng lặp. Bao gồm các lệnh lặp for, while, do, in,và each.
a. Câu lệnh phân nhánh không điều kiện
Phân nhánh không có điều kiện có thể tạo ra bằng hai cách: gọi một hàm
và dùng từ khoá. Để thực hiện phân nhánh ta gọi một trong các từ khóa sau:
goto, break, continue, return,statementthrow
b. Câu lệnh phân nhánh có điều kiện
Phân nhánh có điều kiện được tạo bởi các lệnh điều kiện. Các từ khóa của các
lệnh này như : if, else, switch. Sự phân nhánh chỉ được thực hiện khi biểu thức
điều kiện phân nhánh được xác định là đúng.
 Câu lệnh if...else
Câu lệnh phân nhánh if...else dựa trên một điều kiện. Điều kiện là một biểu
thức sẽ được kiểm tra giá trị ngay khi bắt đầu gặp câu lệnh đó. Nếu điều kiện
được kiểm tra là đúng, thì câu lệnh hay một khối các câu lệnh bên trong thân của
câu lệnh if được thực hiện.
Ta có cú pháp câu điều kiện if... else sau:
if (biểu thức điều kiện)

[else
]
Nếu các câu lệnh trong thân của if hay else mà lớn hơn một lệnh thì các
lệnh này phải được bao trong một khối lệnh, tức là phải nằm trong dấu khối { }:
if (biểu thức điều kiện)
{


….
}

28

[else
{


...
}]
 Câu lệnh switch
Khi có quá nhiều điều kiện để chọn thực hiện thì dùng câu lệnh if sẽ rất rối
rắm và dài dòng, Các ngôn ngữ lập trình cấp cao đều cung cấp một dạng câu lệnh
switch liệt kê các giá trị và chỉ thực hiện các giá trị thích hợp. C# cũng cung cấp
câu lệnh nhảy switch có cú pháp sau:
switch (biểu thức điều kiện)
{
}
case :


[default: ]
Tương tự như câu lệnh if, biểu thức để so sánh được đặt sau từ khóa
switch, tuy nhiên giá trị so sánh lại được đặt sau mỗi các từ khóa case. Giá trị
sau từ khóa case là các giá trị hằng số nguyên.
c. Câu lệnh lặp
C# cung cấp một bộ mở rộng các câu lệnh lặp, bao gồm các câu lệnh lặp for,
while và do... while. Ngoài ra ngôn ngữ C# còn bổ sung thêm một câu lệnh lặp
foreach. Cuối cùng là các câu lệnh nhảy như goto, break, continue, và return.
 Câu lệnh nhảy goto
Lệnh nhảy goto là một lệnh nhảy đơn giản, cho phép chương trình nhảy vô điều
kiện tới một vị trí trong chương trình thông qua tên nhãn. Cú pháp:
Tạo một nhãn
goto đến nhãn
 Vòng lặp while
Ý nghĩa của vòng lặp while là: “Trong khi điều kiện đúng thì thực hiện các
công việc này”. Cú pháp sử dụng vòng lặp while như sau:

29

while (Biểu thức)

Biểu thức của vòng lặp while là điều kiện để các lệnh được thực hiện, biểu thức
này bắt buộc phải trả về một giá trị kiểu bool là true/false. Nếu có nhiều câu lệnh
cần được thực hiện trong vòng lặp while thì phải đặt các lệnh này trong khối
lệnh.
 Vòng lặp do...while
Đôi khi vòng lặp while không thoả mãn yêu cầu trong tình huống sau, chúng ta
muốn chuyển ngữ nghĩa của while là “chạy trong khi điều kiện đúng” thành ngữ
nghĩa khác như “làm điều này trong khi điều kiện vẫn còn đúng”. Nói cách khác
thực hiện một hành động, và sau khi hành động được hoàn thành thì kiểm tra
điều kiện. Cú pháp sử dụng vòng lặp do...while như
sau:
do

while ( điều kiện )
 Vòng lặp for
Vòng lặp for bao gồm ba phần chính:
• Khởi tạo biến đếm vòng lặp
• Kiểm tra điều kiện biến đếm, nếu đúng thì sẽ thực hiện các lệnh bên trong vòng
for
• Thay đổi bước lặp
Cú pháp sử dụng vòng lặp for như sau:
for ([ phần khởi tạo] ; [biểu thức điều kiện]; [bước
lặp])

 Câu lệnh lặp foreach
Vòng lặp foreach cho phép tạo vòng lặp thông qua một tập hợp hay một mảng.
Đây là một câu lệnh lặp mới không có trong ngôn ngữ C/C++. Câu lệnh foreach
có cú pháp chung như sau:
foreach ( in < tên tập hợp>)
30


Do lặp dựa trên một mảng hay tập hợp nên toàn bộ vòng lặp sẽ duyệt qua
tất cả các thành phần của tập hợp theo thứ tự được sắp. Khi duyệt đến phần tử
cuối cùng trong tập hợp thì chương trình sẽ thoát ra khỏi vòng lặp foreach.
 Câu lệnh nhảy break và continue
Khi đang thực hiện các lệnh trong vòng lặp, có yêu cầu như sau: không thực
hiện cáclệnh còn lại nữa mà thoát khỏi vòng lặp, hay không thực hiện các công
việc còn lại của vòng lặp hiện tại mà nhảy qua vòng lặp tiếp theo. Để đáp ứng
yêu cầu trên C# cung cấp hai lệnh nhảy là break và continue để thoát khỏi
vòng lặp. Break khi được sử dụng sẽ đưa chương trình thoát khỏi vòng lặp và
tiếp tục thực hiện các lệnh tiếp ngay sau vòng lặp. Continue ngừng thực hiện
các công việc còn lại của vòng lặp hiện thời và quay về đầu vòng lặp để thực
hiện bước lặp tiếp theo.
2.1.3 Xây dựng lớp, đối tượng
2.1.3.1 Lớp
Để định nghĩa một kiểu dữ liệu mới hay một lớp đầu tiên phải khai báo rồi
sau đó mới định nghĩa các thuộc tính và phương thức của kiểu dữ liệu đó. Khai
báo một lớp bằng cách sử dụng từ khoá class. Cú pháp đầy đủ của khai báo một
lớp như sau:
[Thuộc tính] [Bổ sung truy cập] class <Định danh lớp> [: Lớp cơ sở]
{
phương thức hành động >
}
Định danh lớp chính là tên của lớp do người xây dựng chương trình tạo ra.
Tất cả các thành viên của lớp được định nghĩa bên trong thân của lớp, phần thân
này sẽ được bao bọc bởi hai dấu ({}).
Cũng như nhiều ngôn ngữ lập trình hướng đối tượng khác, kiểu trong C#
được định nghĩa là một lớp (class), và các thể hiện riêng của từng lớp được gọi là

31

đối tượng (object). Ngoài ra còn có các kiểu khác nhau ngoài kiểu lớp như kiểu
liệt kê, cấu trúc và kiểu ủy quyền (delegates).
Hai thành phần chính cấu thành một lớp là thuộc tính hay tính chất và
phương thức hay còn gọi là hành động ứng xử của đối tượng. Trong C# hành vi
được định nghĩa như một phương thức thành viên của lớp. Phương thức chính là
các hàm được định nghĩa trong lớp. Do đó, ta còn có thể gọi các phương thức
thành viên là các hàm thành viên trong một lớp. Các phương thức này chỉ ra rằng
các hành động mà lớp có thể làm được cùng với cách thức làm hành động đó.
Thông thường, tên của phương thức thường được đặt theo tên hành động, ví dụ
như DrawLine() hay GetString().
2.1.3.2 Thuộc tính truy cập
Thuộc tính truy cập quyết định khả năng các phương thức của lớp bao
gồm việc các phương thức của lớp khác có thể nhìn thấy và sử dụng các biến
thành viên hay những phương thức bên trong lớp.
Thuộc tính
Public
Private
Protected
Internal
protected internal

Giới hạn truy cập
Không hạn chế. Những thành viên được đánh dấu
public có thể được dùng bởi bất kì các phương thức của
lớp bao gồm những lớp khác.
Thành viên trong một lớp A được đánh dấu là private
thì chỉ được truy cập bởi các phương thức của lớp A.
Thành viên trong lớp A được đánh dấu là protected
thì chỉ được các phương thức bên trong lớp A và những
phương thức dẫn xuất từ lớp A truy cập.
Thành viên trong lớp A được đánh dấu là internal thì
được truy cập bởi những phương thức của bất cứ lớp
nào trong cùng khối hợp ngữ với A.
Thành viên trong lớp A được đánh dấu là protected
internal được truy cập bởi các phương thức của lớp A,
các phương thức của lớp dẫn xuất của A, và bất cứ lớp
nào trong cùng khối hợp ngữ của A.
Bảng 5: Các thuộc tính truy cập của một lớp

2.1.3.3 Tham số của phương thức
Trong các ngôn ngữ lập trình thì tham số và đối mục được xem là như
nhau, cũng tương tự khi đang nói về ngôn ngữ hướng đối tượng thì ta gọi một

32

hàm là một phương thức hay hành vi. Tất cả các tên này điều tương đồng với
nhau.
Một phương thức có thể lấy bất kỳ số lượng tham số nào, Các tham số này
theo sau bởi tên của phương thức và được bao bọc bên trong dấu ngoặc tròn ().
Mỗi tham số phải khai báo kèm với kiểu dữ liệu của nó. Bên trong thân của
phương thức, các tham số này như những biến cục bộ, giống như là khai báo
biến bên trong phương thức và khởi tạo giá trị bằng giá trị của tham số truyền
vào.
2. 1.3.4 Đối tượng
Những kiểu dữ liệu chuẩn của C# như int, char, float,… là những kiểu dữ
liệu giá trị, và các biến được tạo ra từ các kiểu dữ liệu này được lưu trên stack.
Tuy nhiên, với các đối tượng kiểu dữ liệu tham chiếu thì được tạo ra trên heap,
sử dụng từ khóa new để tạo một đối tượng:
ThoiGian t = new ThoiGian();
t thật sự không chứa giá trị của đối tượng ThoiGian, nó chỉ chứa địa chỉ của đối
tượng được tạo ra trên heap, do vậy t chỉ chứa tham chiếu đến một đối tượng.
C# cũng cung cấp cơ chế thu dọn (garbage collection) hay là hủy đối
tượng. Khi làm việc với các đoạn mã không được quản lý thì cần phải khai báo
tường minh các phương thức hủy để giải phóng các tài nguyên.
2.1.3.5 Khởi tạo biến thành viên
Các biến thành viên có thể được khởi tạo trực tiếp khi khai báo trong quá
trình khởi tạo, thay vì phải thực hiện việc khởi tạo các biến trong bộ khởi dựng.
Để thực hiện việc khởi tạo này rất đơn giản là việc sử dụng phép gán giá trị cho
một biến:
private int Giay = 30; // Khởi tạo
Việc khởi tạo biến thành viên sẽ rất có ý nghĩa, vì khi xác định giá trị khởi
tạo như vậy thì biến sẽ không nhận giá trị mặc định mà trình biên dịch cung cấp.
Khi đó nếu các biến này không được gán lại trong các phương thức khởi dựng thì
nó sẽ có giá trị mà ta đa khởi tạo.

33

2.1.4 Kế thừa và đa hình
2.1.4.1 Kế thừa
Trong ngôn ngữ C#, quan hệ đặc biệt hóa được thực thi bằng cách sử dụng
sự kế thừa.Đây không phải là cách duy nhất để thực thi đặc biệt hóa, nhưng nó là
cách chung nhất và tự nhiên nhất để thực thi quan hệ này. Trong ngôn ngữ C# để
tạo một lớp dẫn xuất từ một lớp ta thêm dấu hai chấm vào sau tên lớp dẫn xuất và
trước tên lớp cơ sở:
public class ListBox : Window
Đoạn lệnh trên khai báo một lớp mới tên là ListBox, lớp này được dẫn xuất từ
Window.
Chúng ta có thể đọc dấu hai chấm có thể được đọc như là “dẫn xuất từ”. Lớp dẫn
xuất sẽ kế thừa tất cả các thành viên của lớp cơ sở, bao gồm tất cả các phương
thức và biến thành viên của lớp cơ sở. Lớp dẫn xuất được tự do thực thi các
phiên bản của một phương thức của lớp cơ sở. Lớp dẫn xuất cũng có thể tạo một
phương thức mới bằng việc đánh dấu với từ khóa new.
Các lớp không được kế thừa các phương thức khởi dựng của lớp cơ sở, do đó lớp
dẫn xuất phải thực thi phương thức khởi dựng riêng. Và chỉ có thể sử dụng
phương thức khởi dựng của lớp cơ sở thông qua việc gọi tường minh.
2.1.4.2 Đa hình
Đa hình được hiểu như là khả năng sử dụng nhiều hình thức của một kiểu,
đa hình có sức mạnh hơn kế thừa. Để tạo một phương thức hỗ tính đa hình,
chúng ta cần phải khai báo khóa virtual trong phương thức của lớp cơ sở.
2.1.4.3 Lớp trừu tượng
Để yêu cầu các lớp con (lớp dẫn xuất) phải thực thi một phương thức của
lớp cơ sở, cần thiết kế một phương thức một cách trừu tượng. Một phương thức
trừu tượng không có sự thực thi. Phương thức này chỉ đơn giản tạo ra một tên
phương thức và ký hiệu của phương thức, phương thức này sẽ được thực thi ở
các lớp dẫn xuất. Những lớp trừu tượng được thiết lập như là cơ sở cho những
lớp dẫn xuất, nhưng việc tạo các thể hiện hay các đối tượng cho các lớp trừu

34