泛型委托使委托在返回值和参数上应用泛型类型参数,和泛型类以及泛型方法原理与用法都类似。比如常见的EventHandler<TEventArgs>,可以支持具有不同事件参数的事件处理。其定义如下:
除此之外,还有一种比较有用的泛型委托:Action<T>和Func<T,TResult>,两者都封装了一个只采用一个参数的方法,不同的是,前者返回void,后者有一个返回值,由TRulst指定类型。扩展点,还有 Aciotn<T1,T2>,Aciotn<T1,T2,T3>,Aciotn<T1,T2,T3,T4>,Func<T1,T2,T3,T4,TResult> 等,暂时最多支持封装四个参数。
Action<T>是.NET Framework 2.0 时支持的语法,Func<T,TResult>是.NET Framework 3.5开始支持的,俺去年才第一次见过,直到今天才想起来整理下。为什么需要这个玩意呢?假设一个情景,有三个CheckBox,分别叫 cbRect,cbCircle,cbPolygon,分别控制没有颜色填充的矩形、圆和多边形。当勾选某个ChechBox,它控制的图形就变为红色。
最无需思考的方法就是,分别为三个CheckBox写下Checked,Unchecked六个事件。当CheckBox的数量增多时,就会发生“事件爆炸”(有这个名词吗?)。另外每个事件的处理也基本一样,发生冗余重复。这说明肯定存在着优化的方法,于是Action<T>就被创造出来解 决这个问题。(难道属于某个设计模式的思想?正在学习设计模式,还没联想到。)
如上所示,把相应的CheckBox和Shape作为参数,实例化个Action泛型委托。在这里只需要处理两次事件,然后在外面相应的调用即可。附加句 无关紧要的,代码环境我测试的是个Silverlight应用程序,顺便熟悉了C# 3.0 新语法中的Lambda表达式和对象初始化器。
代码中注释掉的那句,调用了Func泛型委托,传进去Shape参数,返回这个形状的名字,并赋给CheckBox的Content。Func的代码如下所示,和Aciton不同的是,最后一个参数是返回值。
[SerializableAttribute]
public delegate void EventHandler<TEventArgs>(Object sender,TEventArgs e) where TEventArgs : EventArgs
public delegate void EventHandler<TEventArgs>(Object sender,TEventArgs e) where TEventArgs : EventArgs
Action<T>是.NET Framework 2.0 时支持的语法,Func<T,TResult>是.NET Framework 3.5开始支持的,俺去年才第一次见过,直到今天才想起来整理下。为什么需要这个玩意呢?假设一个情景,有三个CheckBox,分别叫 cbRect,cbCircle,cbPolygon,分别控制没有颜色填充的矩形、圆和多边形。当勾选某个ChechBox,它控制的图形就变为红色。
最无需思考的方法就是,分别为三个CheckBox写下Checked,Unchecked六个事件。当CheckBox的数量增多时,就会发生“事件爆炸”(有这个名词吗?)。另外每个事件的处理也基本一样,发生冗余重复。这说明肯定存在着优化的方法,于是Action<T>就被创造出来解 决这个问题。(难道属于某个设计模式的思想?正在学习设计模式,还没联想到。)
Action<CheckBox, Shape> fillShape = (cb, shape) =>
{
cb.Checked += (s, e) =>
{
shape.Fill = new SolidColorBrush { Color = Colors.Red };
// cb.Content = shapeName(shape);
};
cb.Unchecked += (s, e) =>
{
shape.Fill = null;
cb.Content = String.Empty;
}
};
fillShape(cbRect,spRect);
fillShape(cbCircle, spCircle);
fillShape(cbPolygon, spPolygon);
{
cb.Checked += (s, e) =>
{
shape.Fill = new SolidColorBrush { Color = Colors.Red };
// cb.Content = shapeName(shape);
};
cb.Unchecked += (s, e) =>
{
shape.Fill = null;
cb.Content = String.Empty;
}
};
fillShape(cbRect,spRect);
fillShape(cbCircle, spCircle);
fillShape(cbPolygon, spPolygon);
如上所示,把相应的CheckBox和Shape作为参数,实例化个Action泛型委托。在这里只需要处理两次事件,然后在外面相应的调用即可。附加句 无关紧要的,代码环境我测试的是个Silverlight应用程序,顺便熟悉了C# 3.0 新语法中的Lambda表达式和对象初始化器。
代码中注释掉的那句,调用了Func泛型委托,传进去Shape参数,返回这个形状的名字,并赋给CheckBox的Content。Func的代码如下所示,和Aciton不同的是,最后一个参数是返回值。
Func<Shape, String> shapeName = (shape) =>
{
if (shape.Fill != null)
{
return shape.Name;
}
return String.Empty;
};
{
if (shape.Fill != null)
{
return shape.Name;
}
return String.Empty;
};