代表不仅仅是速记界面吗?

时间:2008-09-18 19:20:25

标签: c# delegates interface

假设我们有:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

现在我们可以将Bar和Baz作为Foos折腾并调用他们的Func方法。

代表们对此进行了简化:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

现在我们可以在Foo代表处围绕Bar和Baz。

除了获得更短的代码外,代表们的真正好处是什么?

10 个答案:

答案 0 :(得分:14)

稍有不同,委托可以访问定义它们的类的成员变量。在C#中(与Java不同),所有内部类都被认为是静态的。因此,如果您使用接口来管理回调,例如一个按钮的ActionListener。实现内部类需要传递(通过构造函数)对回调期间可能需要与之交互的包含类的部分的引用。代表没有此限制,因此减少了实现回调所需的代码量。

更短,更简洁的代码也是值得的好处。

答案 1 :(得分:6)

从软件工程的角度来看,你是对的,委托很像函数接口,因为它们是函数接口的原型。

它们也可以以相同的方式使用:不是传递包含您需要的方法的整个类,而是只传递一个委托。这样可以节省大量代码并创建更易读的代码。

此外,随着lambda表达式的出现,它们现在也可以在飞行中轻松定义,这是一个巨大的奖励。虽然在C#中动态构建类是可能的,但它确实是一个巨大的痛苦。

比较两者是一个有趣的概念。我之前没有考虑过用例和代码结构的观点有多大相似之处。

答案 2 :(得分:3)

委托人与来自调用者角度的单一方法的接口引用共享很多共同点。

在第一个例子中,Baz和Bar是类,可以继承和实例化。在第二个例子中,Baz和Bar是方法。

您不能将接口引用仅应用于与接口契约匹配的任何类。该类必须明确声明它支持该接口。 您可以将委托引用应用于与签名匹配的任何方法。

您不能在接口的合同中包含静态方法。 (尽管可以使用扩展方法来启用静态方法)。 您可以使用委托引用来引用静态方法。

答案 3 :(得分:1)

不,代表是方法指针。然后,您可以确保与委托关联的方法的签名是正确的。

此外,您不需要知道类的结构。这样,您可以使用已编写的方法传递给另一个类中的方法,并定义您希望发生的功能。

看看List<> class with the Find method。现在,您可以定义确定某些内容是否匹配的内容,而不需要类中包含的项目来实现IListFindable或类似内容。

答案 4 :(得分:1)

你可以在代码中传递委托作为参数(好的,技术上委托在编译时成为对象,但这不是重点)。您可以将对象作为参数传递(显然),但是然后您将该类型的对象作为参数绑定到该函数。使用委托,您可以传递任何函数以在具有相同签名的代码中执行,而不管它来自何处。

答案 5 :(得分:1)

可以将委托视为方法的接口,该方法定义方法必须具有哪些参数和返回类型以适合委托

答案 6 :(得分:0)

委托是类型化方法指针。这为您提供了比接口更多的灵活性,因为您可以利用协方差和逆变,并且您可以修改对象状态(您必须使用基于接口的仿函数传递this指针)。

此外,代表们有很多很好的语法糖,可以让你轻松地将它们组合在一起。

答案 7 :(得分:0)

是的,委托可以被认为是一种方法的接口。

答案 8 :(得分:0)

接口和委托是两个完全不同的东西,虽然我理解以类似界面的术语描述代表以便于理解的诱惑......然而,不了解真相可能会导致混乱。

代表受到启发(部分)因为C ++方法指针的黑色艺术不适合某些目的。一个典型的例子是实现消息传递或事件处理机制。委托允许您在不知道类的类型或接口的情况下定义方法签名 - 我可以定义“void eventHandler(Event * e)”委托并在任何实现它的类上调用它。

有关这个经典问题的一些见解,以及为什么代表们需要read this然后this

答案 9 :(得分:0)

至少有一个向Java添加闭包(即匿名委托)的提议,它们等同于具有单个成员方法的接口。