前言
委托)是一种定义方法签名的类型。 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。 您可以通过委托实例调用方法。
委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。
委托
在C#中是一个语言级特性,而在Java语言中没有直接的对应,但是java利用反射即可实现委托!
Func和Action
Func是一种委托,这是在3.5
里面新增的,2.0里面我们使用委托是用Delegate,Func位于System.Core命名空间下,使用委托可以提升效率,例如在反射中使用就可以弥补反射所损失的性能。
Action<T>
和Func<T,TResult>
的功能是一样的,只是Action<T>
没有返回值,Func<T,TResult>
的最后一个参数为返回值。
委托概述
委托具有以下特点:
- 委托类似于 C++ 函数指针,但它们是类型安全的。
- 委托允许将方法作为参数进行传递。
- 委托可用于定义回调方法。
- 委托可以链接在一起;例如,可以对一个事件调用多个方法。
- 方法不必与委托签名完全匹配。 有关更多信息,请参见 在委托中使用变体(C# 和 Visual Basic))。
- C# 2.0 版引入了匿名方法)的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。 匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。 这些功能统称为匿名函数。 有关 lambda 表达式的更多信息,请参见 匿名函数)
何时使用委托而不使用接口
委托和接口都允许类设计器分离类型声明和实现。 任何类)或结构)都能继承和实现给定的接口)。
可以为任何类上的方法创建委托),前提是该方法符合委托的方法签名。
接口引用或委托可由不了解实现该接口或委托方法的类的对象使用。
既然存在这些相似性,那么类设计器何时应使用委托,何时又该使用接口呢?
在以下情况下,请使用委托:
- 当使用事件设计模式时。
- 当封装静态方法可取时。
- 当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
- 需要方便的组合。
- 当类可能需要该方法的多个实现时。
在以下情况下,请使用接口:
- 当存在一组可能被调用的相关方法时。
- 当类只需要方法的单个实现时。
- 当使用接口的类想要将该接口强制转换为其他接口或类类型时。
- 当正在实现的方法链接到类的类型或标识时:例如比较方法。
IComparable) 或泛型版本 IComparable) 就是一个使用单一方法接口而不使用委托的很好的示例。 IComparable 声明 CompareTo) 方法,该方法返回一个整数,指定相同类型的两个对象之间的小于、等于或大于关系。 IComparable 可用作排序算法的基础。 虽然将委托比较方法用作排序算法的基础是有效的,但是并不理想。 因为进行比较的能力属于类,而比较算法不会在运行时改变,所以单一方法接口是理想的。
声明、实例化和使用委托
C# 1.0
及更高版本中,可以按以下示例所示声明委托。
1 | // Declare a delegate. |
实例化
1 | // Create an instance of the delegate. |
C# 2.0
提供了更简单的方法来编写上面的声明,如以下示例所示。
1 | // C# 2.0 provides a simpler way to declare an instance of Del. |
C# 2.0
及更高版本中,还可以使用匿名方法来声明和初始化委托),如以下示例所示。
1 | // Instantiate Del by using an anonymous method. |
C# 3.0
及更高版本中,还可以使用 Lambda 表达式来声明和实例化委托,如以下示例所示。
1 | // Instantiate Del by using a lambda expression. |
C# 3.5
里面新增Func
和Action
1 | public static void threadRun2(Dispatcher dispatcher, Func<string> tFunc, Action<string> mainAction) |