C#中的代理与接口

arj*_*soh 50 c# delegates interface

我想提出这个问题,只要我现在正在努力深入研究代表们的用途和目的,尽管可能会在类似的表述中提出这个问题.

我知道委托作为C++中使用的函数指针.事实上,如果在C#中它们主要用作接口和多态的替代品.既然我可以创建特定类的子类并为它们提供适当的方法,那么除此之外还有什么代表呢?是否存在规定其使用的情况,或仅仅是代表使用时代码的可维护性得到改善?你会推荐他们在接口上的广泛部署吗?

我只是在谈论代表,我想区分他们的角色和事件角色.

Jon*_*eet 73

是的,代表在很多方面都像单方法接口.然而:

  • CLR内置了支持
  • 它们在框架中得到了支持,包括多播能力和异步调用
  • 以方法组转换,lambda表达式,匿名方法的形式提供了额外的C#/ VB语言支持
  • 他们被要求举办活动(即活动和代表是一对配对)
  • 他们的意思是,你并不需要实现为要创建的每个委托实例一个单独的类的接口.

最后一点是最重要的一点 - 考虑LINQ表达式:

var query = collection.Where(x => x > 5)
                      .Select(x => x * x);
Run Code Online (Sandbox Code Playgroud)

现在想象一下,如果表达的逻辑x > 5x * x你不得不写每个表达式一个单独的类,并实现一个接口:克鲁夫特的VS有用的代码量将是可笑的.当然,语言本来可以设计为允许通过单独的类从lambda表达式转换为接口实现,但是你仍然失去了能够简单地编写一个单独的方法并创建一个委托作为目标的好处.你还会失去多人能力.

作为一个类似的思想练习,考虑循环语句,如whilefor.我们真的需要它们goto吗?不.但生活要好得多他们.代表们也是如此 - 实际上是属性,事件等.它们都使开发更简单.

  • 我不认为Linq的例子显示了代表们的优势; 即使委托类型`Func <int,bool>`被接口`IFunc <int,bool>`替换,编译器也可以轻松定义实现该接口的类,并包含一个返回私有静态实例的公共静态属性.对于不关闭任何本地语言的lambda表达式,这种方法的效果大致相同,并且比关闭本地语言的lambda表达式的委托更有效. (5认同)
  • 我想我把原来的问题误解为更理论而不是实际; 如果.net框架是围绕接口而不是委托设计的,那么编译器几乎肯定会为前者提供与后者相同的支持类型.至于闭包,目前创建闭包需要创建一个保存变量的对象和一个委托,该委托保存对该对象的引用和所需的函数; 如果可以使用接口而不是委托,则编译器可以简单地创建一个可以为这两个函数提供服务的对象. (3认同)

das*_*ght 28

最大的实际区别是,您可以为同一个类的同一个委托提供不同的委托实例,而不能使用接口.

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
    }
}
Run Code Online (Sandbox Code Playgroud)


Lio*_*ion 17

何时使用代理而不是接口(MSDN):

委托和接口都允许类设计器分离类型声明和实现.给定的接口可以由任何类或结构继承和实现.可以为任何类的方法创建委托,只要该方法适合委托的方法签名即可.接口引用或委托可以由不了解实现接口或委托方法的类的对象使用.鉴于这些相似之处,类设计者何时应该使用委托,何时应该使用接口?

在以下情况下使用代理:

  • 使用事件设计模式.
  • 期望封装静态方法.
  • 调用者无需访问实现该方法的对象上的其他属性,方法或接口.
  • 需要容易的组合物.
  • 一个类可能需要多个方法的实现.

在以下情况下使用接口:

  • 可以调用一组相关方法.
  • 一个类只需要该方法的一个实现.
  • 使用该接口的类将要将该接口强制转换为其他接口或类类型.
  • 正在实现的方法链接到类的类型或标识:例如,比较方法.

使用单方法接口而不是委托的一个很好的例子是IComparable通用版本IComparable(Of T).IComparable声明CompareTo方法,该方法返回一个整数,该整数指定小于,等于或大于相同类型的两个对象之间的关系.IComparable可以用作排序算法的基础.虽然使用委托比较方法作为排序算法的基础是有效的,但它并不理想.由于比较能力属于类,比较算法在运行时不会改变,因此单方法接口是理想的.

来自C#中的Delegates Vs接口:

代理和接口是C#中的两个不同概念,但它们具有共性.委托和接口都只包含声明.实现由不同的编程对象完成.

  • 有用的答案; 如果您或其他任何人可以添加代表可能有用的第2至第5个要点的示例,那也会很棒.事件模式我认为不需要任何例子,因为它被广泛讨论. (2认同)