Sử dụng Delegate để truyền giá trị trong C#

Xem chủ đề cũ hơn Xem chủ đề mới hơn Go down

Sử dụng Delegate để truyền giá trị trong C#

Bài gửi by nth on 26/08/09, 03:11 pm


[You must be registered and logged in to see this image.]Để có thể viết được một ứng dụng phần mềm, bạn phải biết cách truyền giá trị qua lại giữa các Form.



Tuy
nhiên, khi ta muốn lấy giá trị từ nhiều Form khác, chắc chúng ta sẽ gặp
rắc rối với những cách làm thông thường. Delegate sẽ giúp chúng ta giải
quyết vấn đề.


Trước hết, tôi sẽ trình bày cho các bạn cách truyền giá trị theo cách thông thường.

Dưới đây là giao diện của các Form:

Đây
là giao diện của Form chính. có 2 textbox để hiển thị giá trị lấy từ
các Form khác. 2 button có chức năng hiển thị các form mà mình muốn lấy
giá trị.

[You must be registered and logged in to see this image.]

Còn
đây là giao diện của Form 1, Gồm 1 textbox để nhập giá trị, nút button
để xác nhận giá trị đó và truyền giá trị được nhập trong ô textbox cho
form chính.

[You must be registered and logged in to see this image.]

Tương
tự như Form 1, Form 2 cũng gồm 1 textbox để nhập giá trị, nút button để
xác nhận giá trị đó và truyền giá trị được nhập trong ô textbox cho
form chính.

[You must be registered and logged in to see this image.]

1. Với việc truyền giá trị thông thường:

- Trong Form Chính:

// Ta khai báo trường để lưu giá trị.

private string _getFirstValue = null;

// Thuộc tính này có nhiệm vụ lấy giá trị từ các Form khác.
public string GetFirstValue
{
get
{
return _getFirstValue;
}

set
{
_getFirstValue = value;
}
}

Và viết sự kiện cho nút btnGetValue1:

private void btnGetValue1_Click(object sender, EventArgs e)
{
frmFirstValue first = new frmFirstValue();
first.ShowDialog();
}

Và khi Form chính được hiển thị, ta phải hiển thị nhận được thông qua các thuộc tính GetFirstValue.

private void frmMain_Load(object sender, EventArgs e)
{
txtFirstValue.Text = GetFirstValue;
txtSecondValue.Text = GetSecondValue;
}


- Đối với Form 1: Ta chỉ cần viết sự kiện cho Nút btnSend:

private void btnSend_Click(object sender, EventArgs e)
{
frmMain main = new frmMain();
main.GetFirstValue = txtValue.Text; // Truyền giá trị cho Form chính thông qua thuộc tính GetFirstValue.
main.ShowDialog();
this.Hide();

}


việc
khai báo và xử lý sự kiện đối với Form 2 tương tự. Nhưng trong trường
hợp này, khi lấy giá trị từ 2 Form khác nhau, cách truyền giá trị thông
thường này sẽ không thể làm được. Vậy cách khác, ta sẽ dùng Delegate để
giải quyết vấn đề:

2. Sử Dụng Delegate:

- Dùng Delegate
sẽ giúp chúng ta quyết định xem hàm nào sẽ được trong lúc chạy. Về mặt
kỹ thuật, Delegate là một dạng tham chiếu được sử dụng để đóng gói 1
hàm với giá trị xác thực và kiểu giá trị trả về.

- Trong Form 1: Ta khai báo Delegate có tên là PassData có 1 tham số kiểu string và ko có giá trị trả về.

public delegate void PassData(string value);
public PassData passData;

private void btnSend_Click(object sender, EventArgs e)
{

if (passData != null)
{
passData(txtValue.Text);
}
this.Hide();

}


-
Còn trong Form chính: Ta viết Hàm GetFirstValue phải giống như khi khai
báo Delegate: có 1 giá trị truyền vào là kiểu chuỗi, và không có giá
trị trả về.

public void GetFirstValue(string value)
{
txtFirstValue.Text = value;
}



Ta viết sự kiện cho nút btnGetValue1:

private void btnGetValue1_Click(object sender, EventArgs e)
{

frmFirstValue first = new frmFirstValue();
first.passData = new frmFirstValue.PassData(GetFirstValue);
first.Show();

}

nth
Admin
Admin

Tổng số bài gửi : 550
Số điểm : 1113
Số lần được cám ơn : 33
Ngày đến diễn đàn: : 01/08/2009
Tuổi : 28
Đến từ : Thiên Đường

Xem lý lịch thành viên http://thuhuong.hot4um.com

Về Đầu Trang Go down

Re: Sử dụng Delegate để truyền giá trị trong C#

Bài gửi by nth on 26/08/09, 03:34 pm

---Mảng
Mảng trong C# có nhiều tính năng vượt trội hơn so với C++. Mảng được
cấp phát bộ nhớ trong heap và do đó nó được truyền bằng tham khảo. Bạn
không thể truy xuất một phần tử vượt ngoài giới hạn trong một mảng (có
chỉ số lớn hơn số phần tử trong mảng). Do đó C# đã khắc phục lỗi này.
Ngoài ra C# còn cung cấp một số hàm trợ giúp để xử lý các phần tử trong
mảng. Ta có thể thấy rõ sự khác nhau giữa cú pháp của mảng trong
C++ và C# là:

·Dấu ngoặc vuông được đặt sau tên kiểu chứ không phải sau tên biến.

·Bạn có thể tạo vùng nhớ cho phần tử trong mảng bằng cách dùng từ khóa new.
Ngoài ra C# còn hỗ trợ việc hiện thực mảng một chiều (single
dimensional), đa chiều (multi dimensional) và jagged array (mảng của
mảng). Ví dụ như:

// mảng một chiều đơn giản

int[] array = new int[10];
for (int i = 0;i < array.Length; i++)
array[i] = i;
// mảng hai chiều
int[,] array2 = new int[5,10];
array2[1,2] = 5;

// mảng 3 chiều
int[,,] array3 = new int[5,10,5];
array3[0,2,4] = 9;

// mảng của mảng
int[][] arrayOfarray = = new int[2];
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};

----Indexer

Indexer được dùng để viết một phương thức truy xuất trực tiếp một phần
tử từ một tập hợp bằng cách dùng dấu [ ], như trong mảng. Việc bạn cần
làm chỉ là chỉ rõ chỉ số để truy xuất một phần tử. Cú pháp của
một indexer cũng giống như của thuộc tính một class, ngoại trừ chúng cần
một thông số nhập, đó chính là chỉ số của phần tử cần truy xuất.
Bây giờ chúng ta tiếp tục tham khảo một ví dụ cho vấn đề này. Trong ví
dụ sau bạn sẽ bắt gặp lớp CollectionBase, đó là một lớp thư viện dùng
để tạo ra những tập hợp. Danh sách (list) là một
protected member của lớp CollectionBase, trong đó lưu trữ tập hợp các danh sách.
class Shapes: CollectionBase
{
public void add(Shape shp)
{
List.Add(shp);
}
//indexer
public Shape this[int index]
{
get {
return (Shape) List[index];
}
set {
List[index] = value ;
}
}
}

Boxing/Unboxing
Boxing là một khái niệm mới trong C#. Như đã đề cập ở trên, mọi kiểu dữ
liệu, dựng sẵn hay do người dùng định nghĩa, đều được lấy từ một lớp cơ
bản là Object trong namespace System.
Do đó việc đóng gói những kiểu căn bản hay nguyên thủy vào trong class
Object được gọi là boxing, và thao tác ngược lại được gọi là unboxing.
Ví dụ như:

class Test
{
static void Main()
{
int myInt = 12;
// boxing
object obj = myInt ;
// unboxing
int myInt2 = (int) obj;
}
}

Ví dụ trên cho ta thấy cả hai thao tác boxing và unboxing. Một giá trị
int có thể được chuyển đổi thành đối tượng và chuyển đổi trở lại thành
int. Khi kiểu dữ liệu của một biến cần được chuyển thành một kiểu
truyền bằng tham khảo, một object box được tạo ra để chứa giá trị, và
giá trị được lưu vào box. Unboxing
chỉ là quá trình ngược lại. Khi một object box được trả lại thành kiểu
nguyên thủy , giá trị sẽ được chuyển từ box sang ô nhớ lưu trữ ban đầu.

---Thông số của hàm

Trong C# có 3 loại thông số:
1.Thông số in/ truyền bằng trị.
2.Thông số in– out/truyền bằng tham khảo.
3.Thông số out.

Nếu bạn đã nắm rõ về COM interface và những kiểu thông số của nó, bạn sẽ dễ dàng hiểu được các kiểu thông số của C#.

nth
Admin
Admin

Tổng số bài gửi : 550
Số điểm : 1113
Số lần được cám ơn : 33
Ngày đến diễn đàn: : 01/08/2009
Tuổi : 28
Đến từ : Thiên Đường

Xem lý lịch thành viên http://thuhuong.hot4um.com

Về Đầu Trang Go down

Re: Sử dụng Delegate để truyền giá trị trong C#

Bài gửi by nth on 26/08/09, 03:47 pm

--Thông số in/ truyền bằng trị

Khái niệm thông số truyền bằng trị cũng tương tự như trong C++. Giá trị truyền được chép vào một ô nhớ và được truyền vào hàm.

Ví dụ:

SetDay(5);
...
void SetDay(int day)
{
....
}
---Thông số in – out/truyềnbằng tham khảo

Thông số truyền bằng tham khảo trong C++ được truyền thông qua một con
trỏ hay toán tử &. Trong C#, thông số truyền bằng tham khảo còn
được gọi là thông số in – out, vì khi bạn truyền một địa chỉ tham khảo
của một ô nhớ, bạn đã truyền một giá trị nhập và lấy một giá trị xuất
từ hàm đó.
Bạn không thể truyền một thông số chưa khởi tạo vào một hàm. C# dùng từ
khóa ref để chỉ thông số truyền bằng tham khảo. Bạn cũng có thể dùng từ
khóa ref cho một đối số trong khi truyền nó vào một hàm có thông số
truyền bằng tham khảo. Ví dụ:

int a= 5;
FunctionA(ref a);
Console.WriteLine(a);
void FunctionA(ref int Val)
{
int x= Val;
Val = x* 4;
}

----Thông số out

Là thông số chỉ trả về giá trị là kết quả của một hàm, không đòi hỏi giá trị nhập. C# dùng từ khóa out cho loại tham số này.

int Val;
GetNodeValue(Val);
bool GetNodeValue(out int Val)
{
Val = value;
return true;
}

---Số lượng các thông số và mảng

Để truyền thông số là một mảng trong C#, người ta dùng từ khóa params. Chỉ có thể có một đối số kiểu mảng. Bạn có thể truyền phần tử như là một đối số của mảng đó. Tốt nhất, ta hãy xem ví dụ sau:

void Func(params int[] array)
{
Console.WriteLine(“number of elements {0}”, array.Length);
}
Func();
Func(5);
Func(7,9);
Func(new int[] {3,8,10});
int[] array = new int[8] {1,3,4,5,5,6,7,5};
Func(array);

---Toán tử và biểu thức
Hầu hết các toán tử trong C# hoàn toàn giống như trong C++, do đó biểu
thức cũng vậy. Tuy nhiên C# còn bổ sung thêm một số toán tử mới và hữu
ích. Chúng ta sẽ xem xét vài toán tử trong số đó.

---Toán tử is
Toán tử này được dùng để kiểm tra xem kiểu của các toán hạng có tương
đương hay không. Toán tử is thường được sử dụng trong kịch bản đa ngữ
cảnh. Toán tử
này có hai toán hạng và kết quả trả về có kiểu bool. Chúng ta xem ví dụ sau:

void function(object param)
{
if(param is ClassA)

// something
else if(param is MyStruct)
//something
}
}

---Toán tử as
Toán tử as kiểm tra xem kiểu của các toán hạng có khả đổi hay không,
nếu có thì kết quả trả về là một đối tượng đã được chuyển đổi hay được
box. Nếu đối tượng không chuyển đổi hay box được, kết quả trả về null.
Chúng ta xem ví dụ sau để hiểu rõ hơn về khái niệm này:

Shape shp = new Shape();
//kết quả là null, không chuyển đổi
//kiểu được
Vehicle veh = shp as Vehicle;
Circle cir = new Circle();
Shape shp = cir;
//sẽ được chuyển đổi
Circle cir2 = shp as Circle;
object[] objects = new object[2];
objects[0] = “Aisha”;
object[1] = new Shape();
string str;
for(int i=0; i&< objects.Length; i++)
{
str = objects[i] as string;
if(str == null)
Console.WriteLine(“can not be converted”);
else
Console.WriteLine(“{0}”,str);
}

nth
Admin
Admin

Tổng số bài gửi : 550
Số điểm : 1113
Số lần được cám ơn : 33
Ngày đến diễn đàn: : 01/08/2009
Tuổi : 28
Đến từ : Thiên Đường

Xem lý lịch thành viên http://thuhuong.hot4um.com

Về Đầu Trang Go down

Re: Sử dụng Delegate để truyền giá trị trong C#

Bài gửi by nth on 26/08/09, 03:54 pm

----Câu lệnh
Đa số các câu lệnh trong C# đều tương tự như trong C++, ngoài ra còn có
một số câu lệnh mới được bổ sung và có một vài sự sửa đổi trong một số
câu lệnh cũ. Sau đây là một số câu lệnh mới:

foreach: dùng cho việc thực hiện vòng lặp cho một tập hợp như mảng… Ví dụ:

foreach (string s in array)
Console.WriteLine(s);

lock: dùng để bao một đoạn code thành một section.
checked/unchecked: dùng để kiểm tra tràn trong các toán tử có đối số là số. Ví dụ như:

int x = Int32.MaxValue; x++;
{
x++;
}
unchecked
{
x++; }
}

---Switch

Trong C#, câu lệnh switch được thay đổi như sau:
1.Sau khi thực thi một câu lệnh case, chương trình sẽ không nhảy đến câu lệnh case kế
tiếp. Ví dụ:
int var = 100;
switch (var)
{
case 100:
Console.WriteLine(“”); // không dùng break
case 200:
Console.WriteLine(“”); break;
}

Trong C++, kết quả sẽ là:
Trong C#, bạn sẽ nhận được thông báo lỗi sau:
error CS0163: Control cannot fall through from one case label (‘case 100:’) to another

Tuy nhiên, bạn có thể làm như sau:

switch (var)
{
case 100:
case 200:
Console.WriteLine(“100 or 200”);
break;
}

2.Bạn cũng có thể dùng hằng trong giá trị của case. Ví dụ như:

const string WeekEnd = “Sunday”;
const string WeekDay1 = “Monday”;
....
string WeekDay =
Console.ReadLine();
switch (WeekDay )
{
case WeekEnd:
Console.WriteLine(“It’s weekend!!”);
break;
case WeekDay1:
Console.WriteLine(“It’s Monday”);
break;
}

----Delegate
Delegate cho phép chúng ta lưu sự tham khảo hàm vào một biến. Trong
C++, việc này giống như dùng và lưu con trỏ hàm và chúng ta hay dùng
typedef. Ví dụ:
delegate int Operation(int val1, int val2);
public int Add(int val1, int val2)
{
return val1 + val2;
}

public int Subtract (int val1, int val2)
{
return val1- val2;
}

public void Perform()
{
Operation Oper;
Console.WriteLine(“Enter + or - “);
string optor = Console.ReadLine();
Console.WriteLine(“Enter 2 operands”);
string opnd1 = Console.ReadLine();
string opnd2 = Console.ReadLine();
int val1 = Convert.ToInt32 (opnd1);
int val2 = Convert.ToInt32 (opnd2);
if (optor == “+”)
Oper = new Operation(Add);
else
Oper = new Operation(Subtract);
Console.WriteLine(“ Result ={0}”, Oper(val1, val2));
}

Tính thừa kế và tính đa hình

Trong C# chỉ cho phép sự thừa kế đơn. Nếu bạn muốn thực hiện đa thừa kế, bạn có thể dùng interface. Ví dụ:

class Parent{
}
class Child : Parent

Hàm ảo

Từ khái niệm hàm ảo đến hiện thực khái niệm đa hình trong C# là như
nhau, ngoại trừ việc bạn dùng từ khóa override đối với việc hiện thực
hàm ảo trong lớp con. Lớp cha vẫn sử dụng từ khóa virtual. Lớp nào override phương thức ảo cũng sử dụng từ khóa override.

class Shape
{
public virtual void Draw()
{
Console.WriteLine(“Shape.Draw”);
}
}

class Rectangle : Shape
{
public override void Draw(){
Console.WriteLine(“Rectangle.Draw”);
}
}

class Square : Rectangle
{
public override void Draw()
{
Console.WriteLine(“Square.Draw”);
}
}
class MainClass
{
static void Main(string[] args)
{
Shape[] shp = new Shape[3];
Rectangle rect =
new Rectangle();

shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
}
}
Xuất ra kết quả như sau:
Shape.Draw
Rectangle.Draw
Square.Draw

Ẩn lớp cha bằng cách dùng “new” Trong một lớp con, bạn có thể định nghĩa một hàm mới, ẩn với lớp cha, bằng cách dùng từ khóa new. Trong ví dụ dưới đây, là bản sửa đổi của ví dụ trên, tôi thay thế từ khóa override bằng từ khóa new trong lớp
Rectangle.


class Shape
{
public virtual void Draw()
{
Console.WriteLine(“Shape.Draw”);
}
}
class Rectangle : Shape

{
public new void Draw()
{
Console.WriteLine(“Rectangle.Draw”);
}
}
class Square : Rectangle
{
public new void Draw()
{
Console.WriteLine(“Square.Draw”);
}
}
class MainClass
{
static void Main(string[] args)
{
Console.WriteLine(“Using Polymorphism:”);
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Console.WriteLine(“Using without Polymorphism:”);
rect.Draw();
Square sqr = new Square();
sqr.Draw();
}
}

Kết quả xuất ra như sau
:
Using Polymorphism
Shape.Draw
Shape.Draw
Shape.Draw
Using without Polymorphism:
Rectangle.Draw
Square.Draw

Trong ví dụ trên, phương thức Draw của lớp Rectangle không phải là dạng đa hình của phương thức Draw trong lớp Shape. Thay vì vậy, nó được xem như là một phương thức khác. Do đó, để tránh sự trùng tên giữa lớp cha và lớp con, ta nên dùng từ khóa new.
Lưu ý: bạn không thể dùng hai phương thức cùng tên trong cùng một lớp nếu một phương thức dùng từ khóa new, phương thức kia dùng override hay virtual.

Do đó trong lớp Square, tôi không thể override phương thức Draw của lớp Shape.
Gọi những member của lớp cha Nếu lớp con có dữ liệu member cùng tên với dữ liệu đó trong lớp cha, để tránh bị trùng tên, dữ liệu và hàm member của lớp cha được truy xuất thông qua từ khóa base. Trong ví dụ sau, hãy xem cách constructor của lớp cha được gọi và dữ liệu member được dùng:

public Child(int val) :base(val)
{
myVar = 5;
base.myVar;
}

Hay
public Child(int val)
{
base(val);
myVar = 5 ;
base.myVar;
}

Bài viết này chỉ giới thiệu một cách rất tổng quát về ngôn ngữ C# để các bạn có thể quen với những đặc trưng cơ bản của ngôn ngữ. Mặc dù đã cố gắng đề cập đến hầu hết những khái niệm chính trong C#, nhưng tôi nghĩ vẫn còn rất nhiều thứ khác cần thêm vào và bàn đến.
(Theo: Trần Phạm thanh Tùng - Báo Học Lập Trình)

nth
Admin
Admin

Tổng số bài gửi : 550
Số điểm : 1113
Số lần được cám ơn : 33
Ngày đến diễn đàn: : 01/08/2009
Tuổi : 28
Đến từ : Thiên Đường

Xem lý lịch thành viên http://thuhuong.hot4um.com

Về Đầu Trang Go down

Re: Sử dụng Delegate để truyền giá trị trong C#

Bài gửi by Sponsored content Today at 11:29 pm


Sponsored content


Về Đầu Trang Go down

Xem chủ đề cũ hơn Xem chủ đề mới hơn Về Đầu Trang

- Similar topics

 
Permissions in this forum:
Bạn không có quyền trả lời bài viết