Thứ Tư, 17 tháng 9, 2014
Create a global variable in a GUI
Ask:
Im making a gui which has a two buttons:
function button_browse_Callback(hObject, eventdata, handles)
filename = uigetfile
function button_load_Callback(hObject, eventdata, handles)
fid=fopen(filename,'rt'); ....etc
but I cant do the above because button_load_Callback does not have access to filename. How can I pass the filename from button_browse_callback to button_load_callback? ====================================
Answer by Azzi Abdelmalek on 28 Sep 2013
You don't need global variables, use guidata.
function button_browse_Callback(hObject, eventdata, handles)
filename = uigetfile ...
handles.filename=filename guidata(hObject,handles) %----------------------------------------------------------------------------
function button_load_Callback(hObject, eventdata, handles)
filename=handles.filename fid=fopen(filename,'rt'); ... ==================================================
Answer by Image Analyst on 28 Sep 2013
Another way is to declare the variables global in every function that needs to access them.
function button_browse_Callback(hObject, eventdata, handles)
global baseFileName folder;
[baseFileName, folder] = uigetfile();
function button_load_Callback(hObject, eventdata, handles)
global baseFileName folder;
fullFileName = fullfile(folder, baseFileName);
fid=fopen(fullFileName ,'rt');
Or see the FAQ:
http://matlab.wikia.com/wiki/FAQ#How_can_I_share_data_between_callback_functions_in_my_GUI.28s.29.3F
http://matlab.wikia.com/wiki/FAQ#Are_global_variables_bad.3F
Im making a gui which has a two buttons:
function button_browse_Callback(hObject, eventdata, handles)
filename = uigetfile
function button_load_Callback(hObject, eventdata, handles)
fid=fopen(filename,'rt'); ....etc
but I cant do the above because button_load_Callback does not have access to filename. How can I pass the filename from button_browse_callback to button_load_callback? ====================================
Answer by Azzi Abdelmalek on 28 Sep 2013
You don't need global variables, use guidata.
function button_browse_Callback(hObject, eventdata, handles)
filename = uigetfile ...
handles.filename=filename guidata(hObject,handles) %----------------------------------------------------------------------------
function button_load_Callback(hObject, eventdata, handles)
filename=handles.filename fid=fopen(filename,'rt'); ... ==================================================
Answer by Image Analyst on 28 Sep 2013
Another way is to declare the variables global in every function that needs to access them.
function button_browse_Callback(hObject, eventdata, handles)
global baseFileName folder;
[baseFileName, folder] = uigetfile();
function button_load_Callback(hObject, eventdata, handles)
global baseFileName folder;
fullFileName = fullfile(folder, baseFileName);
fid=fopen(fullFileName ,'rt');
Or see the FAQ:
http://matlab.wikia.com/wiki/FAQ#How_can_I_share_data_between_callback_functions_in_my_GUI.28s.29.3F
http://matlab.wikia.com/wiki/FAQ#Are_global_variables_bad.3F
Thứ Năm, 11 tháng 9, 2014
Thứ Năm, 4 tháng 9, 2014
Delegates và Events trong C# - Phần 2
Có một thực tế đang xảy ra đó là nhiều người rất hay nhầm lẫn giữa
hai khái niệm Delegate và Event, đặc biệt là đối với những người mới làm
quen với ngôn ngữ C# nói riêng và các ngôn ngữ khác thuộc nền tảng .NET
nói chung; Và ngay cả đối với những lập trình viên đã có thâm niên thì
cũng không phải dễ dàng gì có thể phân biệt được rạch ròi sự khác nhau
giữa hai khái niệm này. Bài viết này sẽ đưa ra một số phân tích, so
sánh, qua đó mong muốn có thể làm rõ hơn bản chất của hai khái niệm
Delegate và Event, và giúp chúng ta thấy rõ hơn được sự khác nhau cũng
như mối quan hệ giữa chúng.
Một kiểu delegate được khai báo bằng cách sử dụng từ khóa delegate đi kèm theo với kiểu dữ liệu trả về, tên và danh sách tham số của nó. Để một delegate có thể chứa tham chiếu đến một phương thức khác (hoặc đôi khi ta có thể nói là: delegate đại diện cho một phương thức) thì cả delegate và phương thức mà nó tham chiếu đến phải có cùng nguyên mẫu (signature), có nghĩa là cả hai đều phải có chung kiểu dữ liệu trả về và danh sách tham số.
Ta sẽ xét một ví dụ mà ở đó có một delegate với tên là Calculation được khai báo, kiểu delegate này có kiểu dữ liệu trả về là int, nhận vào hai tham số thuộc kiểu int; Một đối tương của delegate Calculation được tạo ra và tham chiếu đến phương thức Add() của lớp Program, chúng ta có thể để ý rằng cả kiểu delegate Calculation và phương thức Add() có kiểu dữ liệu trả về và danh sách tham số giống nhau.
Tại sao lại cần thiết phải có cả hai khái niệm là delegate và event? Câu trả lời ở đây chính là Encapsulation (tính bao gói).
Đâu là cách để đăng ký một event cho một đối tượng nào đó? Có ba sự lựa chọn:
- Một là, tạo một đối tượng delegate với mức truy cập là public, cách này thì chắc chắn là bị loại đầu tiên, vì nó không đảm bảo được sự đóng gói của đối tượng.
- Cách thứ 2, tạo một đối tượng delegate có mức truy cập là private và đồng thời tạo ra một property để truy xuất đến đối tượng delegate đó; cách này thì khá hơn cách trước, nhưng nhược điểm của nó là ta có thể sẽ có khó khăn khi muốn đăng ký nhiều phương thức với sự kiện này, bởi vì nó chỉ có thể nhận vào một phương thức mà thôi, ví dụ: someInstance.MyEvent = eventHandler, như vậy thì nó sẽ xóa mất phương thức mà trước đó MyEvent đã tham chiếu đến, chú ý đến toán tử “=” chứ không phải là “+=” (Propety thì không thể dùng với toán tử +=).
- Cách thứ 3, và cũng là cách mà ta đang sử dụng, đó là tạo một đối tượng delegate rồi sau đó tạo hai khối lệnh dùng để add và remove các đối tượng delegate. Với cách thứ 3 thì ta đã bảo đảm được tính bao gói một cách toàn diện. Và cách thứ 3 khi được viết ngắn gọn thì chính là cái cách mà chúng ta vẫn thường dùng, kể từ khi bắt đầu làm quen với events.
- Event chỉ có thể được gọi (invoked) ở bên trong class chứa nó, Delegate thì có thể được gọi ở bất cứ đâu (Tùy thuộc vào access modifier).
Trong khi đó, event là cách để một lớp có thể đưa ra các thông báo (notification) đến các lớp khác khi có một sự kiện nào đó xảy ra với bản thân nó. Lớp tung ra event được gọi là publisher, còn lớp nhận và xử lý các event này được gọi là Subcriber.
Event và Delegate là một cách mà C# sử dụng để triển khai cơ chế Observer Pattern (cũng còn được gọi là mô hình Publisher/Subcriber), điều mà trong Java thì được thực hiện bởi các ActionListener.
============================================
Nguồn : http://tapchilaptrinh.vn/2012/07/16/delegates-va-events-trong-c/
1. Delegate
Theo như định nghĩa được đưa ra trên MSDN thì delegate là một kiểu chứa tham chiếu đến một hoặc nhiều phương thức (method), có thể là phương thức của lớp (class’s method) hoặc là phương thức của đối tượng (object’s method). Đối với những ai đã làm việc với ngôn ngữ C hoặc C++ thì có thể thấy delegate gần giống với khái niệm Con trỏ hàm (funtion’s pointer). Tuy nhiên, hiện nay trong nhiều tài liệu vẫn hay dùng chung từ delegate để chỉ đến hai khái niệm khác nhau, gây ra sự mập mờ, đó là Kiểu delegate (delegate type) và Thực thể delegate (delegate instance, hay còn có thể gọi là Đối tượng delegate); Do đó, trong bài viết này chúng ta sẽ không sử dụng từ delegate với nghĩa chung như vậy mà sẽ phân biệt rạch ròi giữa kiểu delegate và đối tượng delegate.Một kiểu delegate được khai báo bằng cách sử dụng từ khóa delegate đi kèm theo với kiểu dữ liệu trả về, tên và danh sách tham số của nó. Để một delegate có thể chứa tham chiếu đến một phương thức khác (hoặc đôi khi ta có thể nói là: delegate đại diện cho một phương thức) thì cả delegate và phương thức mà nó tham chiếu đến phải có cùng nguyên mẫu (signature), có nghĩa là cả hai đều phải có chung kiểu dữ liệu trả về và danh sách tham số.
Ta sẽ xét một ví dụ mà ở đó có một delegate với tên là Calculation được khai báo, kiểu delegate này có kiểu dữ liệu trả về là int, nhận vào hai tham số thuộc kiểu int; Một đối tương của delegate Calculation được tạo ra và tham chiếu đến phương thức Add() của lớp Program, chúng ta có thể để ý rằng cả kiểu delegate Calculation và phương thức Add() có kiểu dữ liệu trả về và danh sách tham số giống nhau.
namespace Test
{public delegate int Calculation(int a, int b);class Program{static int Add(int a, int b){return a + b;}static void Main(string[] args){Calculation ca = new Calculation(Add);int c = ca(5, 4);Console.WriteLine(“c = {0}”, c);Console.ReadLine();}}}
Một cách dùng khác của delegate đó là kỹ thuật sử dụng delegate để
truyền một phương thức vào như là tham số của một phương thức khác, ta
cùng xem ví dụ sau:
using System; namespace Test {Ở ví dụ trên thì ta đã tạo ra một phương thức Calculate() có hai tham số kiểu int và một tham số thuộc kiểu delegate Calculation, với cách làm này thì sau này, khi đem ra sử dụng hàm Calculate() thì ta hoàn toàn có thể tự do truyền vào bất cứ hàm nào để thực hiện tính toán, miễn sao hàm đó phải có cùng nguyên mẫu với kiểu delegate Calculation. Cách làm này còn được sử dụng để triển khai kỹ thuật callback, để tránh làm cho bài viết quá dài thì những ai quan tâm tới vấn đề này, xin vui lòng tìm hiểu thêm ở đây và ở đây.
public delegate int Calculation(int a, int b); class Program {static int Add(int a, int b) {return a + b;} static int Sub(int a, int b) {return a – b;}static int Calculate(int a, int b, Calculation cal) {return cal(a, b);} static void Main(string[] args) {int c = Calculate(5, 4, Add); Console.WriteLine(“c = {0}”, c); int d = Calculate(5, 4, Sub); Console.WriteLine(“d = {0}”, d); Console.ReadLine();}}}
2. Event
Điều đầu tiên mà chúng ta cần khẳng định đó là: Event không phải là đối tượng delegate. Để giúp chúng ta có thể thấy rõ được bản chất của event cũng như sự khác nhau giữa event và delegate thì chúng ta sẽ mượn hai khái niệm khác cũng được sử dụng rất phổ biến trong ngôn ngữ C# đó là Field và Property. Nhìn từ bên ngoài thì Property có vẻ rất giống với Field nhưng bản chất thì Property không phải là Field; Field là một biến, nó chứa dữ liệu, còn Property là một khối lệnh, nó giống với Method hơn. Trong một Property thì ta có hai khối lệnh có thể được khai báo đó là get và set còn Field thì chỉ được khai báo trên một dòng. Thông thường thì người ta sử dụng các Property như là cách để truy xuất đến các Field của lớp đó, như trong ví dụ sau:class Customer {Nhưng đôi lúc ta cũng có thể tạo ra các Property mà không dính dáng gì đến Field cả:
private string name;public string Name {get {return this.name;} set{this.name = value;}}}
class TimeUtil {
public DateTime CurrentTime{get {return DateTime.Now;}}}
Và với sự cải tiến không ngừng của C# nói riêng và .NET nói chung thì bây giờ ta có thể khai báo Property với dạng như sau:
class Customer {Nhìn khối lệnh trên thì thật đơn giản phải không, và hình như là không có bất cứ một Field nào được khai báo trong đó cả, nhưng thực tế thì nó lại khác. Trình biên dịch sẽ tự động tạo ra một field có kiểu string rồi sau đó sử dụng nó để triển khai property Name, và như vậy, đoạn code ở trên thực ra chỉ là một phiên bản rút gọn của lớp Customer mà chúng ta đã xem xét trước đó. Bây giờ thì chúng ta đã nắm rõ ràng hơn về bản chất của Field và Property, chúng ta quay lại trường hợp của Delegate và Event, có thể nói rằng mối liên quan giữa Delegate và Event không khác với mối liên quan giữa Field và Property là mấy. Thông thường, để xây dựng một Event thì ta thực hiện như ví dụ sau:
public string Name {get;set;}}
public delegate void ErrorNotification(string message);và sử dụng:
class MyMachine{
public event ErrorNotification Notify;public void ReportError(string error) {if (Notify != null)Notify(error);}}
static void Main(string[] args) {Ở ví dụ trên thì ta đã khai báo một kiểu delegate có tên là ErrorNotification, sau đó sử dụng nó để tạo một event cho lớp MyMachine với tên là Notify. Nhìn vào đoạn code đó thì sẽ có nhiều người cho rằng event được tạo ra bằng cách tạo một đối tượng mới của kiểu delegate ErrorNotification, nhưng thực tế thì không hề đơn giản như vậy. Một Event thực chất là một khối lệnh, tương tự như Property, nó cũng có hai khối lệnh con được khai báo trong đó là add và remove; khối lệnh add được dùng để đăng ký một phương thức với event, còn khối lệnh remove được dùng để gỡ bỏ một phương thức ra khỏi event đó. Đây chính là cách khai báo một event ngắn gọn, và dễ gây ra nhầm lẫn, ta thử viết lại đoạn code của lớp MyMachineở dạng nguyên thủy của nó:
MyMachine machine = new MyMachine();machine.Notify += new ErrorNotification(PrintString);machine.ReportError(“Some bug ocurred”);Console.ReadLine();}
static void PrintString(string msg){
Console.WriteLine(msg);}
class MyMachine{và đem ra sử dụng:
private ErrorNotification notify;//Delegate instance//Event declarationpublic event ErrorNotification Notify{add{this.notify += value;}remove{this.notify -= value;}}public void ReportError(string error) {if (notify != null)notify(error);}}
static void Main(string[] args) {Hãy chú ý đến cái cách mà chúng ta đã khai báo event Notify của lớp MyMachine với hai khối lệnh add và remove bên trong. Và với cách triển khai cụ thể như vậy, ta có thể dễ dàng thấy rằng Event thực chất là cái cách mà chúng ta sử dụng để truy xuất đến một private delegate ở bên trong một lớp; Ở đây thì value có kiểu là ErrorNotification . Bây giờ thì bạn đã tin cái câu khẳng định trước đó chưa? Event không phải là đối tượng delegate. Và chắc bạn cũng đã thông cảm được với việc tại sao chúng ta lại dựa vào Field và Property để có dẫn dắt vào vấn đề tương quan giữa Delegate và Event, bởi vì thực sự nó có sự tương đồng nhau mà. Tóm lại thì cách khai báo event có dạng:
MyMachine machine = new MyMachine();machine.Notify += new ErrorNotification(PrintString);machine.ReportError(“Some bug ocurred”);Console.ReadLine();}
static void PrintString(string msg){
Console.WriteLine(msg);}
chỉ là một cách viết ngắn gọn, và nó còn có tên gọi là field-like event.public event EventHandler MyEvent
3. Mấu chốt của vấn đề
Đâu là cách để đăng ký một event cho một đối tượng nào đó? Có ba sự lựa chọn:
- Một là, tạo một đối tượng delegate với mức truy cập là public, cách này thì chắc chắn là bị loại đầu tiên, vì nó không đảm bảo được sự đóng gói của đối tượng.
- Cách thứ 2, tạo một đối tượng delegate có mức truy cập là private và đồng thời tạo ra một property để truy xuất đến đối tượng delegate đó; cách này thì khá hơn cách trước, nhưng nhược điểm của nó là ta có thể sẽ có khó khăn khi muốn đăng ký nhiều phương thức với sự kiện này, bởi vì nó chỉ có thể nhận vào một phương thức mà thôi, ví dụ: someInstance.MyEvent = eventHandler, như vậy thì nó sẽ xóa mất phương thức mà trước đó MyEvent đã tham chiếu đến, chú ý đến toán tử “=” chứ không phải là “+=” (Propety thì không thể dùng với toán tử +=).
- Cách thứ 3, và cũng là cách mà ta đang sử dụng, đó là tạo một đối tượng delegate rồi sau đó tạo hai khối lệnh dùng để add và remove các đối tượng delegate. Với cách thứ 3 thì ta đã bảo đảm được tính bao gói một cách toàn diện. Và cách thứ 3 khi được viết ngắn gọn thì chính là cái cách mà chúng ta vẫn thường dùng, kể từ khi bắt đầu làm quen với events.
4. Một vài sự khác nhau về cách sử dụng của Delegate và Event
- Event có thể được khai báo trong interface, Delegate thì không.- Event chỉ có thể được gọi (invoked) ở bên trong class chứa nó, Delegate thì có thể được gọi ở bất cứ đâu (Tùy thuộc vào access modifier).
5. Kết luận
Delegate cung cấp cho ta một cách đơn giản để có thể đại diện cho các lời gọi của phương thức, đặc biệt là các phương thức của đối tượng. Delegate được sử dụng để triển khai các event.Trong khi đó, event là cách để một lớp có thể đưa ra các thông báo (notification) đến các lớp khác khi có một sự kiện nào đó xảy ra với bản thân nó. Lớp tung ra event được gọi là publisher, còn lớp nhận và xử lý các event này được gọi là Subcriber.
Event và Delegate là một cách mà C# sử dụng để triển khai cơ chế Observer Pattern (cũng còn được gọi là mô hình Publisher/Subcriber), điều mà trong Java thì được thực hiện bởi các ActionListener.
============================================
Nguồn : http://tapchilaptrinh.vn/2012/07/16/delegates-va-events-trong-c/
delegate và event trong C# - Phần 1
Giới thiệu
Trong các ứng dụng Windows Form, khi ta click chuột vào một button hay chọn một mục trong listbox, thì đều phát sinh một sự kiện (event). Chương trình có nhiệm vụ xử lý các sự kiện này, chứ không phải các control button hay listbox xử lý. Chính cơ chế này đã tạo ra khả năng tương tác linh hoạt giữa người dùng và chương trình. Người dùng gửi đến chương trình các yêu cầu thông qua các sự kiện, chương trình đáp ứng sự kiện đó và thực hiện một tác vụ nào đó.Những sự kiện đó đều được thực thi bởi cơ chế ủy quyền (delegate). Trong bài viết này, tôi sẽ giới thiệu với các bạn khái niệm delegate và cách sử dụng nó để tạo event (sự kiện) trong C#.
Delegate là gì?
Delegate đơn giản chỉ là một kiểu dữ liệu tham chiếu (reference type) dùng để đóng gói một phương thức với tham số và kiểu trả về xác định. Chúng ta có thể đóng gói bất kỳ phương thức nào trong một delegate thích hợp.Delegate trong C# cũng tương tự như con trỏ hàm trong C++ (function pointer). Bạn sẽ dễ dàng tiếp cận delegate nếu bạn đã từng sử dụng con trỏ hàm trong C++.
Delegate thường được sử dụng để tạo các sự kiện và các hàm callback cho chương trình.
Khai báo delegate
Cú pháp khai báo delegate trong C# như sau:chỉ_định_từ_truy_xuất
delegate
kiểu_trả_về tên_delegate(danh_sách_tham_số);
- chỉ_định_từ_truy_xuất: là một trong các thuộc tính truy cập: private, public, protected, internal.
- kiểu_trả_về: kiểu trả về của phương thức
- tên_delegate: tên của delegate
- danh_sách_tham_số: các tham số của phương thức
public
delegate
void
MyEventHandler(
string
Message);
Để sử dụng delegate, chúng ta phải tạo một thể hiện của nó (tương tự như tạo đối tượng của lớp) và truyền vào phương thức phù hợp (kiểu trả về và tham số) vào hàm khởi tạo của nó. Ví dụ:
using
System;
namespace
DelegateDemo
{
public
delegate
void
MyEventHandler(
string
msg);
public
class
Demo
{
public
static
void
Main()
{
Demo d =
new
Demo();
MyEventHandler handler =
new
MyEventHandler(d.DisplayMsg);
handler(
"Display Message Here."
);
Console.ReadLine();
}
public
void
DisplayMsg(
string
msg)
{
Console.WriteLine(msg);
}
}
}
Trong ví dụ trên, tôi đã tạo ra một delegate tên là MyEventHandler đại diện cho các phương thức có một tham số đầu vào có kiểu string và có kiểu trả về là void. Sau đó, tôi tạo ra một thể hiện của MyEventHandler có tên là handler, truyền vào phương thức khởi tạo của nó là DisplayMsg (dòng 12 trong ví dụ minh họa ở trên). Hàm DisplayMsg này có phần khai báo giống với phần khai báo của delegate MyEventHandler.
Khi các bạn gọi handler và truyền cho nó chuỗi: “Display Message Here.”, nó sẽ gọi hàm DisplayMsg và truyền chuỗi “Display Message Here.” cho hàm này.
Kỹ thuật Multicasting
C# cho phép chúng ta “gắn” nhiều phương thức vào cùng một delegate, miễn là các phương thức này có cùng kiểu trả về và tham số với delegate. Và khi ta gọi delegate này, tất cả các phương thức đã được “gắn” sẽ thi hành cùng lúc. Kỹ thuật này gọi là “Multicasting”.Chú ý : Một multicast delegate chỉ chấp nhận phương thức có kiểu trả về là void.
Để thực hiện Multicasting, ta tạo các thể hiện của một multicast delegate, gắn nó với các phương thức tương ứng. Sau đó dùng toán tử “+” để gom các delegate này vào thành 1 delegate duy nhất. Dưới đây là ví dụ minh họa:
using
System;
namespace
DelegateDemo
{
public
delegate
void
MyEventHandler(
string
msg);
public
class
Demo
{
public
static
void
Main()
{
Demo d =
new
Demo();
MyEventHandler handler1 =
new
MyEventHandler(d.DisplayMsg);
MyEventHandler handler2 =
new
MyEventHandler(d.DisplayMsg);
MyEventHandler handler = handler1 + handler2;
handler(
"Test"
);
Console.ReadLine();
}
public
void
DisplayMsg(
string
msg)
{
Console.WriteLine(msg);
}
public
void
ShowHello(
string
name)
{
Console.WriteLine(
"Hello "
+ name);
}
}
}
Trong ví dụ trên, đầu tiên, chúng ta tạo ra hai delegate là handler1 và hanlder2 gắn hai hàm DisplayMsg() và ShowHello() vào. Sau đó, chúng ta tạo delegate tên là handler và “cộng” hai delegate handler1 và hanlder2 lại với nhau. Như vậy, khi gọi delegate handler, hai delegate handler1 và hanlder2 sẽ đồng thời được gọi.
Ngoài toán tử “+”, C# còn hổ trợ toán tử “+=” và “-=” trên delegate. Ví dụ:
using
System;
namespace
DelegateDemo
{
public
delegate
void
MyEventHandler(
string
msg);
public
class
Demo
{
public
static
void
Main()
{
Demo d =
new
Demo();
MyEventHandler handler =
new
MyEventHandler(d.DisplayMsg);
handler += d.ShowHello;
handler(
"Test"
);
Console.ReadLine();
}
public
void
DisplayMsg(
string
msg)
{
Console.WriteLine(msg);
}
public
void
ShowHello(
string
name)
{
Console.WriteLine(
"Hello "
+ name);
}
}
}
Event (sự kiện)
Một trong những ứng dụng thường thấy nhất của delegate là event. Mỗi sự kiện thực chất là một delegate.Cú pháp khai báo event trong C# như sau:
chỉ_định_từ_truy_xuất event tên_delegate tên_event;
Trong đó:
- chỉ_định_từ_truy_xuất: là một trong các thuộc tính truy cập: private, public, protected, internal.
- tên_delegate: kiểu của delegate đại diện cho event
- tên_event: tên của event
public
delegate
void
MyEventHandler(
string
msg);
public
event
MyEventHandler Click;
Sau đó chúng ta có thể phát ra sự kiện (fire event) bằng cách gọi tên sự kiện và truyền tham số tương ứng.
Ví dụ:
Ví dụ:
namespace
DelegateDemo
{
public
delegate
void
MyEventHandler(
string
msg);
public
class
Window
{
public
event
MyEventHandler Click;
public
Window(
int
top,
int
left)
{
this
.top = top;
this
.left = left;
}
// mô phỏng vẽ cửa sổ
public
virtual
void
DrawWindow() { }
public
void
FireEvent()
{
if
(Click !=
null
)
Click(
"Event Fire."
);
}
// Có hai biến thành viên private do đó hai
// biến này sẽ không thấy bên trong lớp con
int
top;
private
int
left;
}
// ListBox dẫn xuất từ Window
public
class
ListBox : Window
{
public
ListBox(
int
top,
int
left)
:
base
(top, left)
{
//Console.WriteLine("Constructor's ListBox have 2 parameter");
}
// Khởi dựng có tham số
public
ListBox(
int
top,
int
left,
string
theContents)
:
base
(top, left)
// gọi khởi dựng của lớp cơ sở
{
mListBoxContents = theContents;
}
public
override
void
DrawWindow()
{
Console.WriteLine(
"DrawWindow's ListBox"
);
}
// biến thành viên private
private
string
mListBoxContents;
}
public
class
Tester
{
public
static
void
Main()
{
Window w =
new
Window(100, 100);
w.Click += w_Click;
w.FireEvent();
// phát sinh sự kiện
Console.ReadLine();
}
static
void
w_Click(
string
msg)
{
Console.WriteLine(msg);
}
}
}
=============================================
Nguồn: http://quanghd.code5s.com/dotnet/delegate-va-event-trong-csharp.html
Nguồn: http://quanghd.code5s.com/dotnet/delegate-va-event-trong-csharp.html
Thứ Tư, 3 tháng 9, 2014
Giới thiệu về kiểu Generic trong C#
Giới thiệu về Generic Type
Generic là 1 tính năng mới trong .NET Framework 2.0 và và được tích hợp sâu trong Common Language Runtime (CLR). Trong .NET Framework, Generic được giới thiệu là khái niệm về các kiểu tham số và được dùng để thiết kế class và phương thức nhằm để trì hoãn chỉ ra kiểu dữ liệu cho đến khi lớp hoặc phương thức được khai báo hoặc khởi tạo.Ví dụ, bằng cách sử dụng tham số T là tham số chung, bạn có thể tạo 1 class duy nhất mà khi tham chiếu tới, bạn sẽ không gặp bất kỳ lỗi nào xảy ra trong lúc runtime khi ép kiểu hoặc boxing (chuyển giá trị từ value type sang reference type)
Tại sao phải sử dụng kiểu Generic
Một trong những điểm nổi bật của kiểu Generic là cho phép bạn kiểm tra cú pháp trong lúc biên dịch. Bạn có thể sử dụng nhiều kiểu dữ liệu khác nhau với cùng 1 đoạn code (tương tự như khái niệm Template trong C++)Giả sử đầu tiên bạn thiết kế stack để chứa dữ liệu kiểu int:
public class IntStack { readonly int[] _dataArray = new int[100]; int _currentPos; public void Push(int value) { _dataArray[_currentPos++] = value; } public int Pop() { return _dataArray[--_currentPos]; } }
Stack cho phép bạn lưu trữ và nhận dữ liệu theo kiểu LIFO (Last In First Out). Phương thức Push() dùng để đưa dữ liệu vào stack. Phương thức Pop() dùng để nhận dữ liệu từ Stack. Bạn có thể tham khảo thêm ở wikipedia
/// <summary> /// Example Int Stack /// </summary> static void Example1() { // create a new IntStack var stack = new IntStack(); // push some values into the stack stack.Push(2); stack.Push(4); stack.Push(8); // pop values from the stack for (int i = 0; i < 3; i++) { Console.WriteLine("Pop value: {0}", stack.Pop()); } }
Và nếu vào một ngày đẹp trời nào đó, bạn muốn stack lưu trữ kiểu string (stack kiểu int vẫn sử dụng). Thay vì copy và sửa lại, bạn nhận thấy rằng, mọi kiểu dữ liệu được dẫn xuất từ System.Object. Bạn vui mừng và sửa lại:
public class ObjectStack { readonly object[] _dataArray = new object[10]; int _currentPos; public void Push(object value) { _dataArray[_currentPos++] = value; } public object Pop() { return _dataArray[--_currentPos]; } }
/// <summary> /// Object Stack /// </summary> static void Example2() { var stack = new ObjectStack(); stack.Push("2"); stack.Push(4); stack.Push(8); // pop values from the stack for (int i = 0; i < 3; i++) { var a = (int)stack.Pop(); Console.WriteLine("Pop value: {0}", a); } }
Vấn đề là nếu ai đó muốn xài stack kiểu int nhưng lại nhập vào chữ “2”, trình biên dịch sẽ không báo lỗi cho đến lúc runtime
Để khắc phục được điều này, chúng ta sử dụng kiểu Generic.
Sử dụng Generic Type
Đối với 1 class, bạn khai báo như sau:Với T là kiểu bạn truyền vào cho class.
Tương tự với methods, interface, chúng ta khai báo như sau:
public class GenericMethods { public void DoSomething<T, TV>(T a, TV b) { //Do something } } public interface ISessionChannel<TSession> { /*...*/ }
Bạn có thể tham khảo chi tiết tại trang MSDN
Ví dụ tạo 1 Generic Stack
Cách dễ nhất để tạo 1 generic class là bạn hãy tạo 1 class non-generic trước, và sau đó hãy chuyển sang generic class sau.Sau đây tôi sẽ ví dụ chuyển bài Stack từ kiểu int sang kiểu T:
public class GenericStack{} -> public class GenericStack<T>{}
Và bạn thay chỗ nào là kiểu “int” thành kiểu “T”
class GenericStack<T> { readonly T[] _dataArray = new T[10]; int _currentPos; public void Push(T value) { _dataArray[_currentPos++] = value; } public T Pop() { return _dataArray[--_currentPos]; } }
Sử dụng GenericStack:
/// <summary> /// Generic Stack /// </summary> static void Example3() { var stack = new GenericStack<int>(); stack.Push(2); stack.Push(4); stack.Push(8); // pop values from the stack for (int i = 0; i < 3; i++) { var a = stack.Pop(); Console.WriteLine("Pop value: {0}", a); } }
Lưu ý: Có một số trường hợp khi thay từ kiểu cụ thể sang kiểu T sẽ bị lỗi. (Kiểu T không hỗ trợ phép toán +, -, *, /…; hoặc 1 số hàm trên kiểu dữ liệu cụ thể).
Kết luận
Trong bài viết này, tôi đã giới thiệu cho bạn cách dùng kiểu Generic và xây dựng 1 class GenericStack đơn giản. Hi vọng qua ví dụ đó, giúp bạn phần nào nắm được ý nghĩa và tầm quan trọng của kiểu Generic trong lập trình. Chúc các bạn thành công.======================================================
Nguồn: http://d.jou.vn/Article/Gioi-thieu-ve-cac-kieu-Generic-trong-C/68
Đăng ký:
Bài đăng (Atom)