委托与C#中的接口
只要我正在努力挖掘代表的用途和目的,我想提出这个问题,尽pipe可能有类似的提法。
我知道委托作为函数指针在C ++中使用。 事实上,如果在C#中,它们主要作为接口和多态的替代方法。 既然我可以创build一个特定的类的子类,并为它们提供适当的方法,那么除此之外还有什么代表呢? 代表们使用过程中是否存在规定其使用或只是代码可维护性的情况? 你会推荐他们在接口上的广泛部署?
我只是谈论代表,我想把他们的angular色与事件angular色区分开来。
是的,代表在很多方面都像单一方法的接口。 然而:
- CLR为他们提供了支持
- 在他们的框架中有支持,包括多播能力和asynchronous调用
- 还有以方法组转换,lambdaexpression式,匿名方法的forms提供的C#/ VB语言支持
- 他们被授权进行事件(即事件和代表是一对匹配)
- 这意味着您不需要为每个要创build的委托实例在单独的类中实现一个接口。
最后一点是最重要的 – 考虑LINQexpression式:
var query = collection.Where(x => x > 5) .Select(x => x * x);
现在想象一下,如果要expressionx > 5
和x * x
的逻辑,你必须为每个expression式编写一个单独的类,并实现一个接口:cruft vs有用的代码量是荒谬的。 当然,这个语言本来可以被devise成允许lambdaexpression式通过单独的类转换成接口实现,但是你仍然会失去能够简单地编写一个单独的方法并创build一个以它为目标的委托的好处。 你也会失去多重能力。
作为一个类似的思想练习,考虑循环语句,如while
和for
。 我们真的需要他们吗? 不。 但是生活对他们来说更好。 代表们也是如此 – 实际上属性,事件等等,都使得开发变得简单。
最大的实际区别是,您可以为来自同一个类的相同委托提供不同的委托实例,而不能通过接口来实现。
void delegate XYZ(int p); interface IXyz { void doit(int p); } class One { // All four methods below can be used to implement the XYZ delegate void XYZ1(int p) {...} void XYZ2(int p) {...} void XYZ3(int p) {...} void XYZ4(int p) {...} } class Two : IXyz { public void doit(int p) { // Only this method could be used to call an implementation through an interface } }
从何时使用代表而不是接口(MSDN) :
委托和接口都使类devise器能够分离types声明和实现。 给定的接口可以被任何类或结构体inheritance和实现。 只要方法符合代理的方法签名,就可以为任何类上的方法创build委托。 接口引用或委托可以由不知道实现接口或委托方法的类的对象使用。 鉴于这些相似之处,类应用程序什么时候应该使用委托,何时应该使用一个接口呢?
在下列情况下使用委托:
- 使用事件devise模式。
- 需要封装一个静态方法。
- 调用者不需要访问实现该方法的对象上的其他属性,方法或接口。
- 容易组成是理想的。
- 一个类可能需要多个方法的实现。
在以下情况下使用接口:
- 有一组可能被调用的相关方法。
- 一个类只需要一个方法的实现。
- 使用该接口的类将要将该接口转换为其他接口或类types。
- 正在实现的方法链接到类的types或标识:例如比较方法。
使用单一方法接口而不是委托的一个很好的例子是
IComparable
或通用版本IComparable
(Of T)。IComparable
声明了CompareTo方法,该方法返回一个整数,指定相同types的两个对象之间的小于,等于或大于关系。IComparable
可以用作sortingalgorithm的基础。 尽pipe使用委托比较方法作为sortingalgorithm的基础是有效的,但这并不理想。 由于比较的能力属于类,比较algorithm在运行时不会改变,所以单方法接口是理想的。
从C#代表与Vs接口
委托和接口在C#中是两个截然不同的概念,但它们有共同之处。 代表和接口都只包含声明。 实现由不同的编程对象完成。
代表和接口在C#中是两个截然不同的概念。
接口允许扩展一些对象的function,它是接口和实现它的对象之间的契约,而委托只是安全的callback,它们是一种函数指针。
代表接口的唯一真正的优点是
- 在.Net支持的generics之前,代表可以处理不同的参数types。
- 一个类可以创build代表暴露多个不同方法共享相同的签名; 用接口replace委托将意味着每个类都可以公开一个实现每个委托样式接口的方法而不创build辅助类,但是每个附加实现都需要一个辅助类。
当.net不支持generics时,委托是其中的重要组成部分,因为为每个不同的函数签名声明不同的非generics接口是不可行的。 如果.net从一开始就支持generics,那么除了涉及到reflection的某些场景之外,代表就不是必须的了,甚至在那里,使Action<T,U>
成为IAction<T,U>
的实现可能是最有用的IAction<T,U>
(这样代码只需要一些可以Invoke
代码就可以使用该接口)。 基于接口的方法在需要创build暴露多个方法的委托的情况下需要创build单方法类,但是在许多常见情况下,不需要创build单独的委托实例,给予曝光的签名恰恰是一个。
顺便说一下,用接口replace代表不会阻止创build一个通用的组合方法。 事实上,接口协方差可以使得这种方法在许多方面比现有的Delegate.Combine
更好地工作。 实现类似于Delegate.Remove
的方法最多是笨重和令人讨厌的,但是除了需要使用Delegate.Remove
事件订阅pipe理之外,我可以想象没有其他的情况,事件订阅可以最好的使用其他方法来处理。