Phương thức nạp chồng toỏn tử là một thành viờn của lớp, để định nghĩa một phộp toỏn sử dụng cho đối tượng của lớp. Cú ba kiểu
phộp toỏn cú thể nạp chồng: một ngụi (unary operator), hai ngụi
(binary operator) và phộp chuyển kiểu. Cỳ phỏp phương thức nạp
chồng ba kiểu phộp toỏn này như sau:
BổTừ Kiểu Operator PhộpToỏnMộtNgụi(ThamĐối){ //Thõn phương thức
}
BổTừ Kiểu Operator PhộpToỏnHaiNgụi(Tham Đối1, ThamĐối2){
//Thõn phương thức
}
BổTừ implicit/ explicitOperator
KiểuChuyểnĐổi(ThamĐối){
//Thõn phương thức
}
Trong đú:
Bổ từ (Modifier) là cỏc từ khúa public, static hay extern.
Từ khoỏ extern chỉ ra rằng phương thức được gọi tồn tại trong một thư viện DLL
Một phương thức nạp chồng toỏn tử phải là một phương thức
tĩnh static
Kiểu (Data type) là kiểu dữ liệu trả về của phộp toỏn
Phộp toỏn một ngụi là phộp toỏn cú một toỏn hạng như + - ! ~ ++ --
Phộp toỏn hai ngụi là phộp toỏn cú hai toỏn hạng như + - * / % & | ^ << >> == != > < >= <=
Khi nạp chồng phộp toỏn so sỏnh, phải nạp chồng cho phộp toỏn trỏi ngược của nú, vớ dụ nạp chồng phộp so sỏnh ==, ta
phải nạp chồng cả phộp so sỏnh !=, nếu khụng chương trỡnh sẽ bỏo lỗi.
Kiểu chuyển đổi (Convert type) là kiểu dữ liệu cần chuyển đổi thành.
implicit/ explicit là từ khúa cho phộp chuyển kiểu mặc định hay tường minh.
Vớ dụ:
Chuyển kiểu mặc định phõn số a thành double: double d = a;
Chuyển kiểu tường minh phõn số a thành double: double d = (double) a;
Tham đối (Parameter) cú dạng: Kiểu ThamĐối
Thõn phương thức phải cú lệnh trả về giỏ trị cho phộp toỏn
Vớ dụ:Định nghĩa cỏc phộp toỏn cho lớp PhanSo
using System; class PhanSo {
int tu, mau; public int Tu { get { return tu; } }
public int Mau {
get {
return mau; }
public PhanSo(int tu, int mau) { this.tu = tu; this.mau = mau; } // Nạp chồng phộp cộng
public static PhanSo operator+(PhanSo a, PhanSo b) {
PhanSo tong = new PhanSo(a.tu * b.mau + b.tu * a.mau, a.mau * b.mau);
return tong; }
// Nạp chồng phộp nhõn
public static PhanSo operator*(PhanSo a, PhanSo b) {
return new PhanSo(a.tu * b.tu, a.mau * b.mau); }
// Nạp chồng phộp chuyển kiểu mặc định (implicit) thành double // Hay nạp chồng phộp chuyển kiểu tường minh (explicit thay cho implicit)
public static implicit operator double(PhanSo a) {
return (double) a.tu / a.mau; }
// Nạp chồng phộp so sỏnh ==
public static bool operator==(PhanSo a,PhanSo b) { if(a.tu*b.mau == a.mau*b.tu) return true; return false; } // Nạp chồng phộp so sỏnh !=
public static bool operator==(PhanSo a,PhanSo b) {
if (a.tu*b.mau != a.mau*b.tu) return true;
} }
class Test {
public static void Main() {
PhanSo a = new PhanSo(1, 2); PhanSo b = new PhanSo(3, 7); PhanSo c = new PhanSo(2, 3);
// Chuyển kiểu mặc định
Console.WriteLine(a * b + c); // Chuyển kiểu tường minh
Console.WriteLine((double)(a * b + c)); }
}
3.3. THUỘC TÍNH (PROPERTIES)
Thuộc tớnh là một đặc tớnh mới được giới thiệu trong ngụn ngữ C#. Đặc tớnh này cung cấp khả năng bảo vệ cỏc biến dữ liệu bờn trong một lớp bằng việc đọc và ghi chỳng thụng qua thuộc tớnh. Trong ngụn
ngữ khỏc, điều này cú thể được thực hiện thụng qua việc tạo cỏc phương thức truy cập (getter method hay accesser) và phương thức
thiết lập (setter method hay mutator).
Vớ dụ: class ViDu {
int a;
public int geta () {
return this.a; }
public void seta ( int a ) {
this.a = a; }
Cú thể được viết trong C# như sau, và cú thể dễ dàng truy cập
trực tiếp property bờn trong một chương trỡnh C#. class ViDu { int a; public int A { get { return this.a; } set {
// value là biến được tạo ra bởi trỡnh biờn dịch để thay thế
tham đối this.a = value; } } } class Test {
static void Main(string[] args) {
ViDu v = new ViDu(); v.A = 3;
Console.WriteLine(v.A); }
}
Lợi ớch của việc sử dụng thuộc tớnh (property) là cho phộp cỏc thành phần bờn ngoài cú thể truy cập thuộc tớnh một cỏch trực tiếp mà vẫn đảm bảo tớnh đúng gúi trong thiết kế hướng đối tượng.
Thuộc tớnh được tự động cài đặt (Auto-implemented properties):
C# 3.0 cho phộp cỏc thuộc tớnh của lớp được tự động cài đặt (auto- implemented properties). Đa số cỏc properties đều thực hiện cỏc thao tỏc như là ghi và đọc từ 1 biến private nào đú. Trong C# 3.0, nếu như
private thỡ chỉ cần khai bỏo ngắn gọn như sau, trỡnh biờn dịch sẽ tự động tạo biến private vụ danh tương tự khai bỏo tường minh. Để một
thuộc tớnh chỉ được đọc hay ghi giỏ trị trong lớp chứa thuộc tớnh,
thờm từ khúa private trước từ khúa get hay set.
Vớ dụ:
public class ViDu {
public int A { get; set; }
//public int A { get; private set; } }
Thuộc tớnh chỉ đọc (Read only property): Giả sử chỳng ta
muốn tạo lớp Time cung cấp một số thuộc tớnh static để hiển thị ngày hiện hành.
Vớ dụ: using System;
public class RightNow {
public static int Year; public static int Month; public static int Date; static RightNow() { DateTime dt = DateTime.Now; Year = dt.Year; Month = dt.Month; Date = dt.Day; } }
public class Tester {
static void Main() {
RightNow.Year = 2003;
Console.WriteLine("This year: {0}", RightNow.Year.ToString()); }
}
Biến thành viờn chỉ năm hiện hành Year đó được thay đổi thành
2003. Điều này thực sự khụng như mong muốn, cỏc biến tĩnh này
khụng được thay đổi. Nhưng khai bỏo hằng cũng khụng được vỡ biến
tĩnh khụng được khởi tạo cho đến khi phương thức khởi tạo tĩnh được thi hành. Do vậy C# cung cấp bổ sung từ khúa readonly cho
mục đớch này. Với vớ dụ trờn ta khai bỏo lại như sau:
public static readonly int Year; public static readonly int Month; public static readonly int Date;
Khi đú ta phải bỏ lệnh gỏn biến thành viờn Year, vỡ nếu
khụng sẽ bị bỏo lỗi:
// RightNow.Year = 2003;
3.4. THAM CHIẾU PHƯƠNG THỨC (DELEGATE)
Một tham chiếu phương thức (delegate) trong C# tương tự với
con trỏ hàm (function pointer) trong C++. Một delegate cho phộp chỳng ta định nghĩa một hay nhiều phương thức mà delegate tham chiếu đến. Đối tượng delegate được sử dụng để gọi một hay nhiều phương thức mà nú tham chiếu. Delegate là một kiểu tham chiếu đến phương thức, cư xử như phương thức đú, và cú thể được sử dụng như
bất kỳ phương thức với cỏc tham đối và giỏ trị trả về.
Cú ba bước định nghĩa và sử dụng delegate: Khai bỏo
(declaration), khởi tạo (initiation) và gọi phương thức tham chiếu bởi
delegate (invocation).
Khai bỏo delegate: Khai bỏo delegate giống như khai bỏo phương thức mà delegate tham chiếu đến
ĐiềuKhiểnTruyCập delegate Kiểu KiểuDelegate (DanhSỏchThamĐối);
Trong đú:
Kiểu Delegate: Là tờn kiểu delegate
Kiểu (Data type): Kiểu kết quả trả về của phương thức mà delegate tham chiếu đến
Danh sỏch tham đối: Của phương thức mà delegate tham chiếu đến
Vớ dụ:
public delegate void SimpleDelegate(); public delegate void SimpleDelegate(int x);
Khởi tạo delegate: Khởi tạo một đối tượng Delegate, để chỉ ra cỏc phương thức mà delegate tham chiếu đến
KiểuDelegate TờnĐốiTượng = new KiểuDelegate (TờnPhươngThức);
Tờn đối tượng: là tờn đối tượng delegate (delegate object) Tờn phương thức: là phương thức mà delegate tham chiếu đến
Vớ dụ:
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
Để thờm và xúa phương thức delegate tham chiếu đến, sử dụng
phộp toỏn += và -=
Vớ dụ:
SimpleDelegate simpleDelegate += new SimpleDelegate(MyFunc); SimpleDelegate simpleDelegate += new SimpleDelegate(MyFunc1); SimpleDelegate simpleDelegate -= new SimpleDelegate(MyFunc1);
Gọi phương thức tham chiếu bởi delegate:
TờnĐốiTượng(DanhSỏchThamĐối);
Tờn đối tượng: Là tờn đối tượng delegate (delegate object)
Vớ dụ:
simpleDelegate(); simpleDelegate(2);
Vớ dụ: Delegate tham chiếu đến phương thức khụng truyền
tham đối
using System;
namespace BasicDelegate {
// Khai bỏo delegate
public delegate void SimpleDelegate(); class TestDelegate
{
public static void MyFunc() {
Console.WriteLine("Phương thức được gọi bởi delegate");
}
public static void Main() {
// Khởi tạo delegate
SimpleDelegate simpleDelegate = new
SimpleDelegate(MyFunc); // Gọi delegate simpleDelegate(); } } }
Vớ dụ:Delegate tham chiếu đến phương thức cú truyền tham đối
using System;
namespace BasicDelegate {
// Khai bỏo delegate
public delegate void SimpleDelegate(int x); class TestDelegate
{
public static void MyFunc(int n) {
Console.WriteLine("Phương thức được gọi bởi delegate");
Console.WriteLine(n); }
public static void Main() {
// Khởi tạo delegate
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc); // Gọi delegate
simpleDelegate(2); }
} }
Phương thức nặc danh (Anonymous method): Trong phiờn bản
trước của C# 2.0, ta chỉ cú thể khai bỏo delegate tham chiếu đến phương thức đặt tờn (named method). C# 2.0 giới thiệu phương thức
nặc danh (anonymous method) cho phộp ta khi khởi tạo đối tượng
delegate, khụng cần tỏch riờng phương thức mà delegate tham chiếu đến như vớ dụ sau:
// Khai bỏo delegate
public delegate void SimpleDelegate(int x);
// Khởi tạo delegate sử dụng phương thức nặc danh
SimpleDelegate simpleDelegate = delegate(int n) {
Console.WriteLine("Phương thức được gọi bởi delegate"); Console.WriteLine(n);
};
// Gọi delegate
simpleDelegate(2);
Biểu thức Lambda (Lambda expression): C# 3.0 đưa ra khỏi niệm
biểu thức lambda (lambda expression). Biểu thức lambda là một thao
tỏc nặc danh (anonymous function) chứa biểu thức hay khối lệnh, cú
thể sử dụng để tạo delegate hay cõy biểu thức (expression tree). Biểu
thức lambda sử dụng phộp toỏn lambda =>. Vế trỏi phộp toỏn lambda
là cỏc tham đối đầu vào và vế phải là biểu thức hay khối lệnh: (DanhSỏchThamĐối) => BiểuThức/ KhốiLệnh
Nếu khụng cú tham đối thỡ cỳ phỏp sẽ như sau:
() => BiểuThức/ KhốiLệnh
Biểu thức lambda: x => x * x cú thể được gỏn đến một đối tượng delegate như sau:
// Khai bỏo delegate
public delegate int SimpleDelegate(int x); // Khởi tạo delegate sử dụng biểu thức lambda SimpleDelegate simpleDelegate = x => x * x; // Gọi delegate
int y = simpleDelegate(2); Console.WriteLine(y);
Hay biểu thức lambda chứa khối lệnh cú thể gỏn đến đối tượng delegate như sau:
// Khai bỏo delegate
public delegate void SimpleDelegate(int x, int y); // Khởi tạo delegate sử dụng biểu thức lambda SimpleDelegate simpleDelegate = (x, y) => { Console.WriteLine(x); Console.WriteLine(y); }; // Gọi delegate simpleDelegate(2,3); 3.5. SỰ KIỆN (EVENT)
C# hỗ trợ lập trỡnh sự kiện bằng cỏch bổ sung khỏi niệm sự kiện
Một eventlà một thành viờn của lớp, cho phộp một lớp khai bỏo
sự kiện xảy ra khi chạy chương trỡnh, và xỏc định một delegate sẽ được gọi khi xảy ra sự kiện. Delegate cú thể cú một hay nhiều phương thức kết hợp sẽ được gọi khi sự kiện phỏt sinh. Nhiều sự kiện
cú thể chia sẻ cựng một delegate.
Cỏc bước để tạo một sự kiện trong C# là khai bỏo một sự kiện
(event declaration), đăng ký sự kiện (event accessor) và phỏt sinh sự
kiện (event raise).
Khai bỏo event: Để khai bỏo event trong một lớp, đầu tiờn phải
khai bỏo một kiểu delegate tham chiếu đến phương thức được gọi khi
sự kiện phỏt sinh.
Vớ dụ:
public delegate void Handler();
Kế tiếp ta khai bỏo event, một event được khai bỏo giống như
một biến kiểu delegate, ngoại trừ việc bổ sung từ khúa event, event thường khai bỏo public, nhưng cú thể sử dụng cỏc điều khiển truy
cập khỏc:
[BổTừ] event KiểuDelegate TờnSựKiện;
Bổ từ (Modifier) là tựy chọn, cú thể là new, virtual, override, abstract, sealed, static, extern.
Kiểu delegate (Delegate type) là kiểu delegate được gọi khi
phỏt sinh sự kiện.
Vớ dụ:
public event Handler WokenUp;
Đăng ký event: Mó đăng ký event để thờm hay xúa delegate từ
một event. Đăng ký event cú thể thực hiện khi kết hợp và xúa một
delegate vào event, sử dụng toỏn tử += và -=.
TờnSựKiện += new KiểuDelegate(TờnPhươngThức);
TờnSựKiện -= new KiểuDelegate(TờnPhươngThức); Tờn phương thức: Là phương thức mà delegate tham chiếu đến
Vớ dụ:
private void HandleEvent(object sender, EventArgs e) {
Console.WriteLine("Your animal has woken up. Feed it now!"); }
WokenUp += new Handler(HandleEvent);
Khi đó gọi sự kiện, xúa delegate khỏi event bằng cỏch sử dụng
toỏn tử -=.
WokenUp -= new Handler(HandleEvent);
Phỏt sinh một event: Khi đó khai bỏo event, cú thể sử dụng event như là một biến của kiểu delegate. Phỏt sinh một event như gọi
một delegate
TờnSựKiện(DanhSỏchThamĐối)
Danh sỏch tham đối là tham đối của phương thức mà delegate tham chiếu đến.
Vớ dụ: if (WokenUp != null) WokenUp(); Vớ dụ: using System; using System.Threading; namespace ConsoleApplication1 {
//Khai bỏo kiểu delegate
public delegate void Handler(); public class Animal
{
//Khai bỏo event
public event Handler WokenUp; public void Sleep()
{
Thread.Sleep(3000); // Phỏt sinh event
if (WokenUp != null) WokenUp(); }
}
public class Farmer {
public Farmer() {
//Thờm delegate vào event Animal a = new Animal();
a.WokenUp += new Handler(HandleEvent); a.Sleep();
}
private void HandleEvent() {
Console.WriteLine("Your animal has woken up. Feed it now!"); }
public static void Main() {
Console.WriteLine("Begin execution"); Farmer f = new Farmer();
Console.WriteLine("End execution"); Console.ReadKey(); } } } 3.6. CHỈ MỤC (INDEXER)
Một indexer là một thành viờn của lớp cho phộp một đối tượng
của một lớp hay struct được chỉ số như là một mảng. Cỏc thành phần
của mảng được truy cập sử dụng dấu ngoặc vuụng. Khai bỏo indexer giống như thuộc tớnh, ngoại trừ khi cỏc phương thức truy cập và thiết
lập cú tham đối. Một indexer được khai bỏo như sau:
[BổTừ] Kiểuthis [DanhSỏchThamĐối] {
//Mó kết hợp với indexer
Trong đú:
Bổ từ là tựy chọn, và phải là điều khiển truy cập hay một
trong cỏc từ khúa new, virtual, sealed, override, hay abstract. Kiểu (Return type) là kiểu dữ liệu trả về của indexer
Danh sỏch tham đối (Parameter list) của indexer. Ít nhất phải
cú một tham đối truyền cho indexer. Tham đối khai bỏo ref và out là khụng được phộp
Mó kết hợp với indexer tương tự cỏc phương thức truy cập và thiết lập sử dụng cho thuộc tớnh
Vớ dụ: using System; namespace ConsoleApplication1 { class SampleCollection<T> { // Khai bỏo một mảng
private T[] arr = new T[100];
// Định nghĩa Indexer, cho phộp đối tượng của lớp hiện hành sử
// dụng []
public T this[int i] {
get {
//Indexer này đơn giản trả về phần tử của mảng
return arr[i]; } set { arr[i] = value; } } } class Program {
static void Main(string[] args) {
SampleCollection<string> stringCollection = new SampleCollection<string>();
stringCollection[0] = "Hello, World";
System.Console.WriteLine(stringCollection[0]); }
} }
3.7. KIỂU CẤU TRÚC (STRUCT)
Cấu trỳc là một kiểu giỏ trị, được sử dụng để đúng gúi tập hợp cỏc đặc tớnh liờn quan. Tương tự định nghĩa lớp, cấu trỳc chứa biến
thành viờn, thuộc tớnh và phương thức, tham chiếu phương thức, sự
kiện và chỉ mục. Cấu trỳc giỳp bạn tổ chức dữ liệu khoa học hơn, mó
được trong sỏng dễ hiểu hơn và cải tiến tốc độ chương trỡnh và bộ nhớ
sử dụng.
Cấu trỳc là kiểu giỏ trị, trong khi lớp là kiểu tham chiếu. Cấu
trỳc khụng cú phương thức hủy, nhưng lớp cú thể cú phương thức
hủy. Một điểm khỏc nhau nữa giữa cấu trỳc và lớp là cấu trỳc khụng
thể kế thừa, nhưng cú thể cài đặt giao tiếp như lớp. Vỡ vậy, cỏc thành viờn của cấu trỳc khụng thể khai bỏo protected.
Nếu cú khụng nhiều thành viờn, hay chỉ cú thuộc tớnh trong cấu
trỳc và khụng kế thừa hay đa hỡnh, bạn nờn sử dụng kiểu cấu trỳc thay
cho kiểu lớp.
Cấu trỳc cũng cú phương thức khởi tạo, nhưng cấu trỳc khụng
thể định nghĩa một phương thức khởi tạo mà khụng cú tham đối. Cấu trỳc định nghĩa cỏc phương thức khởi tạo với cỏc tham đối chớnh xỏc như tất cả cỏc biến thành viờn.
Giống lớp, phương thức khởi tạo mặc định khởi tạo tất cả cỏc
thuộc tớnh về giỏ trị rỗng, nguyờn là 0, thực là 0.0, boolean là false, ký tự là ‘\0’, và kiểu tham chiếu là null.
Cỳ phỏp định nghĩa và sử dụng cấu trỳc tương tự lớp.
Vớ dụ: using System; struct Rectangle {
int width; public int Width {
get { return width;} set { width = value; } }
int height; public int Height {
get { return height; } set { height = value; } }
public Rectangle(int width, int height) {
this.width = width; this.height = height; }
public int Area() {
return this.width * this.height; }
}
class StructExample {
static void Main() {
Rectangle rect1 = new Rectangle(); rect1.Width = 1;
rect1.Height = 3;
Console.WriteLine("rect1: {0}, {1}", rect1.Width, rect1.Height); Rectangle rect2 = new Rectangle(5, 7);
Console.WriteLine("rect2: {0}, {1}", rect2.Width, rect2.Height); Console.WriteLine("Area of rect2: {0}", rect2.Area());
Console.ReadKey(); }
3.8. KIỂU TỔNG QUÁT (GENERIC TYPE)
C# 2.0 hỗ trợ lập trỡnh kiểu tổng quỏt với lớp, cấu trỳc, giao
tiếp, tham chiếu phương thức và phương thức.
Tham đối kiểu tổng quỏt cho phộp bạn định nghĩa lớp, cấu trỳc,
giao tiếp, tham chiếu phương thức hay phương thức sử dụng kiểu
tổng quỏt bất kỳ, sẽ được chỉ rừ kiểu khi bạn khởi tạo lớp, cấu trỳc,
hay sử dụng phương thức. Lập trỡnh kiểu tổng quỏt hỗ trợ tớnh tỏi sử
dụng cao, tiết kiệm thời gian cụng sức lập trỡnh, mà độ hoàn thiện của