C#泛型与委托
时间:2015.10.28
泛型
定义
- T
- 可以作为各种类型进行使用,方便编程
在函数中的定义
private T MyFunc<T>(T a) { object tmp = a; if (a is int) return (T)((object)(Convert.ToInt32(tmp) * 3)); else if (a is double) return (T)((object)(Convert.ToDouble(tmp) * 0.5)); else return a; }
- 如上,在泛型不能直接和其他类型的数据进行操作,需要先将泛型转化为转化为另外一个操作数的类型,之后转化为object,再强制转化为T(具体的类型不能直接转化为泛型)。
委托
定义
- 直接定义如下即可
- public delegate T Calculator(T x);
对委托的函数定义如下:
private T MyFunc<T>(T a) { if (a is int) return (T)((object)(Convert.ToInt32(a) * 3)); else if (a is double) return (T)((object)(Convert.ToDouble(a) * 0.5)); else return a; }
- 只要和委托的参数类型相同,都可以作为委托的“实例化”
具体的调用方法如下:
int[] a = new int[] { 1, 3, 5 }; MyUtility.Calculate<int>(a,MyFunc);
作用
- 实现插件式编程:可以执行任意一个参数形式相同的函数的方法
多播委托
- 一个委托可以指向不止一个方法,即可以实现多个方法,见下面的实例
首先定义一个委托
public delegate void ProgressReporter(int percent);
按键响应事件如下:
private void button4_Click(object sender, RoutedEventArgs e) { ProgressReporter p = null; p += WriteToConsole; p += WriteToFile; MyUtility.MyMatch(p); Console.WriteLine("finished"); } static void WriteToConsole(int per) { Console.WriteLine(per+"%"); } static void WriteToFile(int per) { System.IO.File.AppendAllText("E:/test.txt", per + "%\r\n"); }
MyMatch定义如下:
public static void MyMatch(ProgressReporter p) { if (p != null) { for (int i = 0; i <= 10; i++) { p(i * 10); Thread.Sleep(100); } } }
Func和Action委托
- 相同点:都是新的委托,接受多个参数,都是为了简化代码(不使用delegate),Func 和 Action 委托,除了ref参数和out参数,基本上能适用于任何泛型委托的场景
- 不同点:Func有返回值,Action无返回值
Action委托示例如下:
//使用了兼容的参数 private void button5_Click(object sender, RoutedEventArgs e) { Action<object> action = null; action = MyAction; action(3); } private void MyAction(object a) { Console.WriteLine(a); }
不用再用delegate定义委托,非常方便。
委托的比较
- 对于具体相同的目标方法的委托被视为相等;
- 对于多播委托,相同的方法有对应的相同的顺序,则也被视为相等
事件
角色
- 广播者:包括一个委托字段,通过调用委托发出广播
- 订阅者:通过+=和-=的形式开始或者停止订阅
定义
直接在声明委托时加event关键字即可,如下
public event PriceChangedHandler PriceChanged;
实例分析
- 以下是价格改变时会调用价格改变函数
MyMobile的定义
public class MyMobile
{
private int price = 0;
public PriceChangedEventHandler priceChanged;
public MyMobile(int p)
{
price = p;
}
public int Price
{
get
{
return price;
}
set
{
int oldPrice = price;
this.price = value;
priceChanged(oldPrice,price);
}
}
}
按键响应以及对应的价格改变函数
private void button1_Click(object sender, RoutedEventArgs e)
{
MyMobile m = new MyMobile(1000);
m.priceChanged += changedP;
m.Price = 500;
}
private void changedP(int o, int p)
{
if (o != p)
{
Console.WriteLine("ori: "+o+" , now: "+p);
}
}