1. Trang chủ
  2. » Công Nghệ Thông Tin

Phần 1: Delegate docx

13 128 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 13
Dung lượng 75,15 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Tất cả các hàm có đặc tả hàm giống với đặc tả của delegate trên các tham số truyền vào có kiểu giống nhau, kết quả trả về giống nhau đều có thể dùng để delegate trên tham chiếu tới.. Mộ

Trang 1

Phần 1: Delegate

Một delegate là kiểu tham chiếu tới một phương thức( hàm, mình sẽ gọi là hàm trong suốt bài này luôn nghen ) Một khi delegate được gán tham chiếu tới một hàm, nó sẽ giống hệt hàm đó Hàm delegate được dùng giống hệt các hàm bình thường khác, nghĩa là cũng có kiểu trả về, có tham số truyền vào.

Ví dụ:

public delegate int PerformCalculation( int x, int y );

Ở ví dụ trên, tên của delegate sẽ là "PerformCalculation" Các bạn nên chú ý: khai báo delegate thường rất dễ bị

nhầm lẫn với khai báo hàm.

Tất cả các hàm có đặc tả hàm giống với đặc tả của delegate trên (các tham số truyền vào có kiểu giống nhau, kết quả trả

về giống nhau) đều có thể dùng để delegate trên tham chiếu tới Do đó chỉ cần biết đặc tả của delegate là chúng ta có thể tạo hàm của riêng mình để delegate tham chiếu tới Ví dụ về các hàm mà delegate trên có thể tham chiếu tới:

public int AddMethod(int x, int y);

public int SubtractMethod(int x, int y);

public int PowerMethod(int x, int y);

Bây giờ việc cuối cùng là chúng ta tạo ra đối tượng delegate cụ thể (instance của đặc tả delegate ở trên) và sau đó cho

nó tham chiếu tới một hàm bất kì (cùng đặc tả) Ví dụ:

PerformCalculation addDelegate = new PerformCalculation(AddMethod);

Bây giờ thì thử viết chương trình cộng hai số dùng delegate trên:

<CODE>

public delegate int PerformCalculation(int x, int y);

class TestDelegate

{

public int AddMethod(int m, int n)

{

System.Console.WriteLine("Thuc hien phep cong trong ham AddMethod");

System.Console.WriteLine("{0} + {1} = {2} ", m, n, m + n);

return m + n;

}

[STAThread]

static void Main()

{

TestDelegate phepToan = new TestDelegate();

int x, y;

string strInput = string.Empty;

do

{

try

{

Console.Write("Nhap vao so thu nhat: ");

strInput = Console.ReadLine();

x = System.Convert.ToInt16(strInput);

Console.Write("Nhap vao so thu hai: ");

strInput = Console.ReadLine();

y = System.Convert.ToInt16(strInput);

break;

}

catch(FormatException)

{

Console.WriteLine("Vui long nhap lai");

}

}while(true);

PerformCalculation add = new PerformCalculation(phepToan.AddMethod);

int tong = add(x,y);

System.Console.WriteLine("Gia tri cua tong: " + tong);

}

}

Trang 2

Phần 2: Events và Delegates

Event, dịch ra nghĩa tiếng Việt là sự kiện Và đúng thiệt, mình thấy trong Net nó dùng event theo đúng nghĩa sự kiện thiệt Bây giờ hãy bỏ ngôn ngữ lập trình sang một bên và xem xét event trong cuộc sống đời thường của chúng ta Ví dụ về một sự kiện: "xe quảng cáo show diễn rao: Tối nay ca sĩ Lươn Bàng Quan sẽ biểu diễn tại sân đình" chẳng hạn Trong sự kiện trên chúng ta thấy xe quảng cáo chính là đối tượng phát sinh ra sự kiện rao show diễn, còn tên ca sĩ và địa điểm biểu diễn là thông tin đi kèm với sự kiện trên, ta cũng có thể thấy vì xe quảng cáo có loa phóng thanh rất to nên ko phải một mình ta nghe mà còn nhiều người khác nghe nữa, tức là cùng lúc có thể có nhiều đối tượng nhận sự kiện Trong nhiều đối tượng nhận được sự kiện trên, mỗi đối tượng sẽ có những cách xử lý sự kiện trên khác nhau:

+ Một số người là fan hâm mộ thì sẽ sắp xếp đi xem.

+ Một số không quan tâm đến các show diễn thì sẽ không làm gì cả,

+ v v.

event trong Net cũng giống y chang không khác gì sự kiện trên Một event sẽ có các thông tin:

+ Đối tượng phát ra event (được khai báo kiểu Object)

+ Các thông tin đi kèm với event (được gọi là EventArgs)

+ Các hàm của các đối tượng đăng kí nhận event sẽ có cách xử lí event khác nhau.

Với các đặc tính trên, events sẽ dùng delegate để kích họat (trigger) hàm xử lí của các hàm xử lí đã đăng kí nhận events Bây giờ ta sẽ dùng ví dụ cũ để làm ví dụ:

// Declare a delegate

delegate void PerformCalculation( object sender, PerformCalculationEvenArgs e );

class PerformCalculationEvenArgs : System.EventArgs // lớp chứa thông tin đi kèm với event, nhất thiết phải kế thừa từ lớp System.EventArgs

{

int x, y;

public PerformCalculationEvenArgs(int _x, int _y)

{

x = _x;

y = _y;

}

public int X

{

get {return this.x;}

}

public int Y

{

get {return this.y;}

}

}

class myTestdelegate

{

public static void AddMethod(object sender, PerformCalculationEvenArgs e)

{

System.Console.WriteLine("Thuc hien phep cong trong ham AddMethod");

System.Console.WriteLine("{0} + {1} = {2} ", e.X, e.Y, e.X + e.Y); }

public static void SubtractMethod(object sender, PerformCalculationEvenArgs e) {

System.Console.WriteLine("Thuc hien phep tru trong ham SubtractMethod");

System.Console.WriteLine("{0} - {1} = {2} ", e.X, e.Y, e.X - e.Y); }

public static void PowerMethod(object sender, PerformCalculationEvenArgs e)

{

System.Console.WriteLine("Thuc hien phep luy thua x^y trong ham PowerMethod"); System.Console.WriteLine("{0} ^ {1} = {2} ", e.X, e.Y, e.X ^ e.Y); }

}

class TestDelegate

{

public event PerformCalculation Calculations = null;// khai báo một event cụ thể

Trang 3

[STAThread]

static void Main()

{

TestDelegate phepToan = new TestDelegate();

phepToan.Calculations += new PerformCalculation(myTestdelegate.AddMethod); // đăng kí hàm xử lí event

phepToan.Calculations += new

PerformCalculation(myTestdelegate.SubtractMethod); // đăng kí hàm xử lí event

phepToan.Calculations += new PerformCalculation(myTestdelegate.PowerMethod);// đăng kí hàm xử lí event

int x, y;

string strInput = string.Empty;

do

{

try

{

Console.Write("Nhap vao so thu nhat: ");

strInput = Console.ReadLine();

x = System.Convert.ToInt16(strInput);

Console.Write("Nhap vao so thu hai: ");

strInput = Console.ReadLine();

y = System.Convert.ToInt16(strInput);

break;

}

catch(FormatException)

{

Console.WriteLine("Vui long nhap lai");

}

}while(true);

Console.WriteLine("Raise event");

if (phepToan.Calculations != null)// kiem tra xem event co ham nao dang ki xu

li khong, nhất thiết phải kiểm tra trước khi raise event

phepToan.Calculations(phepToan, new PerformCalculationEvenArgs(x,y));// raise event

}

}

Delegate có thể được xem như là kiểu đối tượng mới trong C#, mà có môt số điểm quen thuộc với lớp Chúng tồn tại trong tình huống mà ta muốn truyền phương thức xung quanh những phương thức khác, để minh hoạ ta xem dòng mã sau:

int i = int.Parse(“99″);

- Chúng ta quen với việc truyền dữ liệu đến một phương thức như là thông

số, vì vậy ý tường truyền phương thức như là thông số nghe có vẻ hơi lạ đối

với chúng ta Tuy nhiên có trường hợp mà ta có 1 phương thức mà làm 1 điều

gì đó, nhiều hơn là xử lí dữ liệu, phương thức đó có thể cần làm điều gì đó

mà liên quan đến việc thực thi phương thức khác phức tạp hơn, bạn không

biết vào lúc nào thì phương thức thứ hai sẽ được biên dịch Thông tin đó chỉ biết vào lúc chạy, và chính vì lí do

đó mà phương thức 2 sẽ cần truyền vào như là thông số cho phương thức đầu tiên Điều này nghe có vẻ hơi khó hiểu, nhưng nó sẽ được làm rõ hơn trong 1 vài ví dụ sau:

Luồng bắt đầu: C# có thể bảo máy tính bắt đầu một chuỗi thực thi mới song song với việc thực thi

đương thời 1 chuỗi liên tiếp này gọi là luồng,và việc bắt đầu này được làm bằng cách dùng phương

thức, Start() trên 1 thể hiện của lớp cơ sởSystem.Threading.Thread Khi chương trình bắt đầu chạy,nơi nó bắt

Trang 4

đầu làmain() Tương tự như vậy khi bạn muốn máy tính chạy một chuỗi thực thi thì bạn phải báo cho máy tính biết bắt đầu chạy là ở đâu Bạn phải cung cấp cho nó chi tiết của phương thức mà việc thực thi có thể bắt đầu – nói cách khác, phương thức Thread.Start()phải lấy 1 thông số mà định nghĩa phương thức được thi hành bởi luồng

Lớp thư viện chung khi 1 nhiệm vụ chứa đựng nhiệm vụ con mà mã của các nhiệm vụ con này

được viết trong các thư viện chỉ có sử dụng thư viện mới biết nó làm gì Ví dụ, chúng ta muốn viết một lớp chứa một mảng đối tuợng và sắp nó tăng dần 1 phần công việc được lặp lại là lấy 2 đối tượng trong lớp so sánh với nhau để xem đối tượng nào đứng truớc.nếu ta muốn lớp có khả năng sắp xếp bất kì đối tượng nào, không có cách nào có thể làm được việc so sánh trên Mã client dùng mảng đối tượng của ta sẽ bảo cho ta biết cách so sánh cụ thể đối tượng mà nó muốn sắp xếp Nói cách khác, mã client sẽ phải truyền cho lớp của ta phương thức thích hợp mà có thể được gọi, để làm việc so sánh

Nguyên tắc chung là: mã của ta sẽ cần thông báo cho thời gian chạy NET biết phương thức nào xử lí tình huống nào

- Vì thế chúng ta phải thiết lập những nguyên tắc mà đôi lúc, những phương thức cần lấy chi tiết của phương thức khác như là thông số Kế tiếp chúng ta sẽ minh họa cách làm điều đó, cách đơn giản nhất là truyền tên của phương thức như là thông số Giả sử chúng ta muốn bắt đầu một luồng mới, và chúng ta có phương thức được gọi là entrypoint(), mà ta muốn luồng bắt đầu chạy từ đó:

void EntryPoint()

{

// làm những gì luồng mới cần làm

}

- Có thể chúng ta bắt đầu luồng mới với một đoạn mã:

Thread NewThread = new Thread();

Thread.Start(EntryPoint); // sai

- Thật sự đây là cách đơn giản nhất Trong một vài ngôn ngữ dùng cách này như C và C++ (trong c và c++ thông số entrypoint là con trỏ hàm) Không may, cách thực thi trực tiếp này gây ra một số vấn đề về an toàn kiểu Nhớ rằng ta đang lập trình hướng đối tượng, phương thức hiếm khi nào tồn tại độc lập, mà thường là phải kết hợp với phương thức khác trưóc khi được gọi Vì vậy NET không cho làm điều này, thay vào đó nếu

ta muốn truyền phương thức ta phải gói chi tiết của phương thức trong một loại đối tượng mới là 1 delegate delegate đơn giản là một kiểu đối tượng đặc biệt – đặc biệt ở chỗ, trong khi tất cả đối tượng chúng ta định nghĩa trước đây chứa đựng dữ liệu, thì delegate chứa đựng chi tiết của phương thức

1.

Dùng delegate trong C#

- Đầu tiên ta phải định nghĩa delegate mà ta muốn dùng ,nghĩa là bảo cho trình biên dịch biết loại phương thức

mà delegate sẽ trình bày.sau đó ta tạo ra các thể hiện của delegate

Cú pháp:

delegate void VoidOperation(uint x);

- Ta chỉ định mỗi thể hiện của delegate có thể giữ một tham chiếu đến 1 phương thức mà chứa một thông số uint và trả vầ kiểu void

Trang 5

- Ví dụ khác: nếu bạn muốn định nghĩa 1 delegate gọi là twolongsOp mà trình bày 1 hàm có 2 thông số kiểu long và trả về kiểu double ta có thể viết :

delegate double TwoLongsOp(long first, long second);

- Hay 1 delegate trình bày phương thức không nhận thông số và trả về kiểu string

delegate string GetAString();

- Cú pháp cũng giống như phương thức, ngoại trừ việc không có phần thân của phương thức, và bắt đầu với delegate, ta cũng có thể áp dụng các cách thức truy nhập thông thường trên một định nghĩa delegate – public, private, protected …

public delegate string GetAString();

- Mỗi lần ta định nghĩa một delegate chúng ta có thể tạo ra một thể hiện của nó mà ta có thể dùng đề lưu trữ các chi tiết của 1 phưong thức cụ thể

- Lưu ý: với lớp ta có 2 thuật ngữ riêng biệt: lớp để chỉ định nghĩa chung, đối tượng để chỉ một thể hiện của 1 lớp, tuy nhiên đối với delegate ta chỉ có một thuật ngữ là ’1 delegate’ khi tạo ra một thể hiện của delegate ta cũng gọi nó là delegate Vì vậy cần xem xét ngữ cảnh để phân biệt

- Đoạn mã sau minh hoạ cho 1 delegate:

static void Main(string[] args)

{

int x = 40;

GetAString firstStringMethod = new GetAString(x.ToString);

Console.WriteLine("String is" + firstStringMethod());

// With firstStringMethod initialized to x.ToString(),

// the above statement is equivalent to saying

// Console.WriteLine("String is" + x.ToString());

}

- Trong mã này, ta tạo ra delegate GetAString, và khởi tạo nó để nó tham khảo đến phương

thức ToString() của một biến nguyên x chúng ta sẽ biên dịch lỗi nếu cố gắng khởi tạo FirstStringMethod với bất

kì phương thức nào có thông số vào và kiểu trả về là chuỗi

- 1 đặc tính của delegate là an kiểu an toàn ( type-safe) để thấy rằng chúng phải đảm bảo dấu ấn ( signature) của phương thức được gọi là đúng Tuy nhiên 1 điều thú vị là, chúng không quan tâm kiểu của đối tượng phương thức là gì khi gọi hoặc thậm chí liệu rằng phương thức đó là static hay là một phương thức thể hiện

- Để thấy điều này ta mở rộng đoạn mã trên, dùng delegate FirstStringMethod để gọi các phương thức khác trên những đối tượng khác – 1 phương thức thể hiện và 1 phương thức tĩnh Ta cũng dùng lại cấu

trúc currency, và cấu trúc currency đã có overloadriêng của nó cho phương thức ToString().để xem xét delegate với phương thức tĩnh ta thêm 1 phương thức tĩnh với cùng dấu ấn như currency:

struct Currency

{

public static string GetCurrencyUnit()

{

return "Dollar";

}

}

Trang 6

- Bây giờ ta sử dụng thể hiện GetAString như sau:

private delegate string GetAString();

static void Main(string[] args)

{

int x = 40;

GetAString firstStringMethod = new GetAString(x.ToString);

Console.WriteLine("String is " + firstStringMethod());

Currency balance = new Currency(34, 50);

firstStringMethod = new GetAString(balance.ToString);

Console.WriteLine("String is " + firstStringMethod());

firstStringMethod = new GetAString(Currency.GetCurrencyUnit);

Console.WriteLine("String is " + firstStringMethod());

}

- Đoạn mã này chỉ cho ta biết làm thế nào để gọi 1 phương thức qua trung gian là delegate, đăng kí lại

delegate để tham chiếu đến một phương thức khác trên 1 thể hiện khác của lớp

- Tuy nhiên ta vẫn chưa nắm rõ được quy trình truyền 1 delegate đến 1 phương thức khác, cũng như chưa thấy được lợi ích của delegate qua ví dụ trên Như ta có thể gọi trực tiếpToString() từ int hay currency mà không cần delegate Ta cần những ví dụ phức tạp hơn để hiểu rõ delegate Ta sẽ trình bày 2 ví dụ: ví dụ 1 đơn giản sử dụng delegate để gọi vào thao tác khác Nó chỉ rõ làm thế nào để truyền delegate đến phương thức và cách sử dụng mảng trong delegate Ví dụ 2 phức tạp hơn là lớp BubbleSorter, thực thi 1 phương thức sắp xếp mảng đối tượng tăng dần lớp này sẽ rất khó viết nếu không có delegate

a Ví dụ SimpleDelegate

- Trong ví dụ này ta sẽ tạo lớp MathOperations mà có vài phương thức static để thực thi 2 thao tác trên kiểu double, sau đó ta dùng delegate để gọi những phương thức này Lớp như sau:

class MathsOperations

{

public static double MultiplyByTwo(double value)

{

return value * 2;

}

public static double Square(double value)

{

return value * value;

}

}

- Sau đó ta gọi phương thức này như sau:

using System;

namespace SimpleDelegate

{

delegate double DoubleOp(double x);

Trang 7

class MainEntryPoint

{

static void Main()

{

DoubleOp[] operations =

{

new DoubleOp(MathsOperations.MultiplyByTwo),

new DoubleOp(MathsOperations.Square)

};

for (int i = 0; i < operations.Length; i++)

{

Console.WriteLine("Using operations[{0}]:", i);

ProcessAndDisplayNumber(operations[i], 2.0);

ProcessAndDisplayNumber(operations[i], 7.94);

ProcessAndDisplayNumber(operations[i], 1.414);

Console.WriteLine();

}

}

static void ProcessAndDisplayNumber(DoubleOp action, double value)

{

double result = action(value);

Console.WriteLine(

"Value is {0}, result of operation is {1}", value, result);

}

}

}

- Trong đoạn mã này ta khởi tạo 1 mảng delegate doubleOp Mỗi phần tử của mảng được khởi động để tham chiếu đến 1 thao tác khác được thực thi bởi lớp MathOperations Sau đó, nó lặp xuyên suốt mảng,ứng dụng mỗi thao tác đến 3 kiểu giá trị khác nhau Điều này minh họa cách sử dụng delegate – là có thể nhóm những phương thức lại với nhau thành mảng để sử dụng, để ta có thể gọi một vài phương thức trong vòng lặp

- Chỗ quan trọng trong đoạn mã là chỗ ta truyền 1 delegate vào phương thứcProcessAndDisplayNumber(), ví dụ:

ProcessAndDisplayNumber(operations[i], 2.0);

- Ở đây ta truyền tên của delegate, nhưng không có thông số nào.cho rằng operation[i]là 1 delegate :

 operation[i] nghĩa là ‘delegate’,nói cách khác là phương thức đại diện cho delegate

 operation[i](2.0) nghĩa là ‘ gọi thực sự phương thức này, truyền giá trị vào trong ngoặc’

 Phương thức ProcessAndDisplayNumber() được định nghĩa để lấy 1 delegate như là thông số đầu tiên của nó :

static void ProcessAndDisplayNumber(DoubleOp action, double value)

Trang 8

 Sau đó khi ở trong phương thức này , ta gọi:

double result = action(value);

 Thể hiện delegate action được gọi và kết quả trả về được lưu trữ trong result

chạy ví dụ ta có:

SimpleDelegate

Using operations[0]:

Value is 2, result of operation is 4

Value is 7.94, result of operation is 15.88

Value is 1.414, result of operation is 2.828

Using operations[1]:

Value is 2, result of operation is 4

Value is 7.94, result of operation is 63.0436

Value is 1.414, result of operation is 1.999396

b Ví dụ BubleSorter

- Sau đây ta sẽ xem 1 ví dụ cho thấy sự hữu ích của delegate Ta sẽ tạo lớp bublesorter Lớp này thực thi 1 phương thức tĩnh, Sort() lấy thông số đầu là 1 mảng đối tượng, và sắp xếp lại chúng tăng dần Ví dụ để sắp xếp 1 mảng số nguyên bằng thuật toán Bubble sort :

///đây không phải là 1 phần của ví dụ

for (int i = 0; i < sortArray.Length; i++)

{

for (int j = i + 1; j < sortArray.Length; j++)

{

if (sortArray[j] < sortArray[i]) // problem with this test

{

int temp = sortArray[i]; // swap ith and jth entries

sortArray[i] = sortArray[j];

sortArray[j] = temp;

}

}

}

- Thuật toán này tốt cho số nguyên, nhưng ta muốn phương thức sort() sắp xếp cho mọi đối tượng,ta thấy vấn

đề nằm ở dòng if(sortArray[j] < sortArray[i]) trong đoạn mã trên.bởi ta muốn so sánh 2 đối tượng trên mảng mà cái nào là lớn hơn Chúng ta có thể sắp xếp kiểu int, nhưng làm thế nào để sắp xếp những lớp chưa biết hoặc không xác định cho đến lúc chạy.câu trả lời là mã client, mà biết về lớp muốn sắp xếp, phải truyền 1 delegate gói trong một phương thức sẽ làm công việc so sánh

- Định nghĩa delegate như sau:

delegate bool CompareOp(object lhs, object rhs);

- Và xây dựng phương thức sort() là :

static public void Sort(object [] sortArray, CompareOp gtMethod)

Trang 9

- Phần hướng dẫn cho phương thức này sẽ nói rõ rằng gtmethod phải tham chiếu đến 1 phương thức static có

2 đối số, và trả về true nếu giá trị của đối số thứ 2 là ‘lớn hơn’ (nghĩa là năm sau trong mảng) đối số thứ nhất Mặc dù ta có thể sử dụng delegate ở đây, nhưng cũng có thể giải quyết vấn đề bằng cách sử dụng interface NET xây dựng 1 interfaceIComparer cho mục đích này Tuy nhiên, ta sử dụng delegate vì loại vấn đề này thì thường có khuynh hướng dùng delegate

- Sau đây là lớp bublesorter :

class BubbleSorter

{

static public void Sort(object[] sortArray, CompareOp gtMethod)

{

for (int i = 0; i < sortArray.Length; i++)

{

for (int j = i + 1; j < sortArray.Length; j++)

{

if (gtMethod(sortArray[j], sortArray[i]))

{

object temp = sortArray[i];

sortArray[i] = sortArray[j];

sortArray[j] = temp;

}

}

}

}

}

- Để dùng lớp này ta cần định nghĩa 1 số lớp khác mà có thể dùng thiết lập mảng cần sắp xếp Ví dụ công ty điện thoại có danh sách tên khách hàng, và muốn sắp danh sách theo lương.mỗi nhân viên trình bày bởi thể hiện của một lớp , Employee:

class Employee

{

private string name;

private decimal salary;

public Employee(string name, decimal salary)

{

this.name = name;

this.salary = salary;

}

public override string ToString()

{

return string.Format(name + ", {0:C}", salary);

}

public static bool RhsIsGreater(object lhs, object rhs)

{

Trang 10

Employee empLhs = (Employee)lhs;

Employee empRhs = (Employee)rhs;

return (empRhs.salary > empLhs.salary) ? true : false;

}

}

- Lưu ý để phù hợp với dấu ấn của delegate CompareOp, chúng ta phải định nghĩaRhsIsGreater trong lớp này lấy 2 đối tượng để tham khảo,hơn là tham khảo employeenhư là thông số.điều này có nghĩa là ta phải ép kiểu những thông số vào trong tham khảoemployee để thực thi việc so sánh

- Bây giờ ta viết mã yêu cầu sắp xếp :

namespace Wrox.ProCSharp.AdvancedCSharp

{

delegate bool CompareOp(object lhs, object rhs);

class MainEntryPoint

{

static void Main()

{

Employee[] employees =

{

new Employee("Karli Watson", 20000),

new Employee("Bill Gates", 10000),

new Employee("Simon Robinson", 25000),

new Employee("Mortimer", (decimal)1000000.38),

new Employee("Arabel Jones", 23000),

new Employee("Avon from 'Blake's 7'", 50000)};

CompareOp employeeCompareOp = new CompareOp(Employee.RhsIsGreater);

BubbleSorter.Sort(employees, employeeCompareOp);

for (int i = 0; i < employees.Length; i++)

Console.WriteLine(employees[i].ToString());

}

}

}

- Chạy mã này sẽ thấy employees được sắp xếp theo lương

BubbleSorter

Bill Gates, £10,000.00

Karli Watson, £20,000.00

Arabel Jones, £23,000.00

Simon Robinson, £25,000.00

Ngày đăng: 29/07/2014, 08:20

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w