1 - Generic là gì?
-- Hiểu nôm na, đơn giản generic cũng là một kiểu dữ liệu trong C#, nó cũng như là int, float, string, bool.... nhưng điểm khác biệt ở đây generic nó là một kiểu dữ liệu "tự do", mình nói tự do có nghĩa là nó có thể là kiểu dữ liệu nào cũng được, tùy vào mục đích sử dụng của mình, nó như là 1 kiểu đại diện cho tất cả các kiểu dữ liệu còn lại vậy : . Hơi khó hiểu nhưng hãy xem tiếp những phần dưới thì sẽ dễ hiểu hơn ^^
2 - Generic Class:
-- Đặt vấn đề: Bây giờ mình cần xây dựng 1 class myClass, trong đó có 2 hàm khởi dựng:
-- Hàm đầu tiên: Thông số truyền vào là kiểu Int => Xuất ra kiểu dữ liệu của tham số truyền vào và giá trị của tham số đó.
-- Hàm thứ hai: Thông số truyền vào là kiểu string => Xuất ra kiểu dữ liệu của tham số truyền vào và giá trị của tham số đó.
Quá đơn giản đúng ko , như vậy ta có đoạn code sau:
PHP:
public class myClass
{
//Ham khoi dung 1
public myClass(int myInt)
{
Console.WriteLine("My Type is: " + myInt.GetType());
Console.WriteLine("My value is: " + myInt.ToString());
}
//Ham khoi dung 2
public myClass(string myStr)
{
Console.WriteLine("My Type is: " + myStr.GetType());
Console.WriteLine("My value is: " + myStr.ToString());
}
}
class MainClass
{
public static void Main()
{
myClass myclass1 = new myClass(5);
myClass myclass2 = new myClass("Hello");
Console.ReadKey();
}
}
Giải pháp đưa ra sẽ là Generic Class ^^
Cú pháp khai báo một Generic Class: [attributes] class_name<T>{}
Đơn giản chỉ vậy ^^
Bây giờ các bạn xem đoạn code sau:
PHP:
public class myClass<T>
{
T mytype;
public myClass(T myType)
{
this.mytype = myType;
Console.WriteLine("My Type is: " + typeof(T));
}
//Lay gia tri cua tham so truyen vao
public T getValue()
{
return this.mytype;
}
}
class MainClass
{
public static void Main()
{
myClass<int> myclass1 = new myClass<int>(100);
int nInt = myclass1.getValue();
Console.WriteLine("My value is: {0}", nInt);
myClass<string> myclass2 = new myClass<string>("Hello moto ^^");
string myString = myclass2.getValue();
Console.WriteLine("My value is: {0}", myString);
Console.ReadKey();
}
}
Ta thấy bây giờ đoạn code của myClass gọn hơn rất nhiều nhờ Generic, chỉ 1 đoạn code ngắn như vậy nhưng có phạm vi sử dụng rất lớn, tức là có thể gọi đựoc rất nhiều hàm khởi dựng như vấn đề đặt ra
Ví dụ bây giờ ta mún gọi một hàm khởi dựng mà tham số truyền vào là bool thì sao? Rất đơn giản là trong hàm Main bạn chỉ cần gọi như sau:
PHP:
myClass<bool> myclass3 = new myClass<bool>(true);
bool myBool = myclass3.getValue();
Console.WriteLine("My value is: {0}", myBool);
Ngoài ra C# còn cho phép chúng ta sử dụng Generic Class với 2 tham số truyền vào đó là T và V. Cú pháp khai báo như sau:
PHP:
class myClass2<T, V> {}
2 -- Generic Delegate:
-- Như đã biết, bản chất của Delegate là nó chỉ có thể gọi tới những hàm có cùng kiểu trả về và cùng kiểu dữ liệu của tham số truyền vào hàm được ủy thác.
-- Như vậy vấn đề đặt ra là làm cách nào để 1 hàm ủy thác duy nhất có thể gọi tới nhiều hàm khác nhau có kiểu dữ liệu của tham số truyền vào khác nhau , rườm rà quá, đi vào ví dụ cụ thể luôn nhá
-- Xây dựng 1 hàm ủy thác có khả năng gọi tới 2 hàm có 2 chức năng khác nhau đó là:
-- Hàm 1: Tham số truyền vào là một chuỗi, hàm sẽ xuất ra chuỗi truyền vào dưới dạng IN HOA.
-- Hàm 2: Tham số truyền vào là số nguyên, hàm sẽ xuất ra giá trị của tham số truyền vào nhân 10.
--> Nếu cố ý đọc NHẦM đề thì ta có thể xây dựng hàm ủy thác như sau:
PHP:
/*Khai báo hàm ủy thác
* Kiểu dữ liệu truyền vào là tùy ý
*/public delegate void MyDelegate(object arg);
class Program{
static void MyTarget(object arg)
{
if (arg is int)//Nếu tham số truyền vào là Int
{
int i = (int)arg;
Console.WriteLine("arg*10 is: {0}", i*10);
}
if (arg is string)//Nếu tham số truyền vào là string
{
string s = (string)arg;
Console.WriteLine("arg in uppercase is: {0}", s.ToUpper());
}
}
static void Main(string[] args)
{
MyDelegate d = new MyDelegate(MyTarget);
d("string");
MyDelegate d2 = new MyDelegate(MyTarget);
d2(10);
Console.ReadKey();
}
}
Nhưng rõ ràng làm như vậy là không thực tế cho lắm so với yêu cầu đưa ra. Như vậy thì phải làm sao trong khi bản chất của Delegate là chỉ gọi được những hàm có cùng số lượng tham số và cùng kiểu dữ liệu
-- Giải pháp đưa ra là: Dĩ nhiên là Generic Delegate roài (Đang PR cho em nó mà
-- Cú pháp khai báo một Generic Delegate: [attributes] delegate returntype delegate_name<T>(T [parameters])
Như vậy với yêu cầu trên ta có đoạn code sau
PHP:
public delegate void MyGenericDelegate<T>(T arg);
class Program{
//2 ham duoc uy thac
static void StringTarget(string arg)// Ham 1 voi tham so truyen vao kieu string
{
Console.WriteLine("arg in uppercase is: {0}", arg.ToUpper());
}
// Ham 1 voi tham so truyen vao kieu int
static void IntTarget(int arg)
{
Console.WriteLine("arg*10 is: {0}", arg*10);
}
static void Main(string[] args)
{
// Khai bao ham uy thac voi thong so truyen vao kieu string
MyGenericDelegate<string> strTarget = new MyGenericDelegate<string>(StringTarget);
strTarget("my string");
// Khai bao ham uy thac voi thong so truyen vao kieu int
MyGenericDelegate<int> intTarget = IntTarget;
intTarget(10);
Console.ReadKey();
}
}
Đoạn code trên quá rõ ràng rùi đúng hem
Giờ mình chơi sang hơn 1 tí, ở ví dụ trên các hàm được gọi tới từ hàm ủy thác đề trả về cùng kiểu là void, giờ sang hơn là muốn trả về gì cũng được nhưng hạn chế ở đây là kiểu trả vè của hàm và tham số truyền vào phải giống nhau ^^
PHP:
//Khai bao ham uy thac tra ve kieu tu dodelegate T MyDelegate<T>(T v);
class MainClass{
//Ham 1 tra ve int và tham so truyen vao cung int
static int sum(int v)
{
return v;
}
//Ham 2 tra ve string và tham so truyen vao cung string
static string reflect(string str)
{
return str;
}
public static void Main()
{
MyDelegate<int> intDel = sum;
Console.WriteLine(intDel(100));
MyDelegate<string> strDel = reflect;
Console.WriteLine(strDel("Hello Ajinomoto ^^"));
Console.ReadKey();
}
}
0 nhận xét