11

假设我们有:

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);
}

现在我们可以将 Bar 和 Baz 作为 Foo 代表折腾。

除了获得更短的代码之外,委托的真正好处是什么?

4

10 回答 10

14

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

更短、更简洁的代码也是一个有价值的好处。

于 2008-09-18T19:29:00.100 回答
6

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

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

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

比较两者是一个有趣的概念。从用例和代码结构的角度来看,我以前没有考虑过这些想法有多相似。

于 2008-09-18T19:29:56.667 回答
3

从调用者的角度来看,委托确实与具有单一方法的接口引用有很多共同点。

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

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

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

于 2008-09-18T19:33:56.407 回答
1

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

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

使用 Find 方法查看List<> 类。现在您可以定义什么来确定某物是否匹配,而不需要类中包含的项目来实现 IListFindable 或类似的东西。

于 2008-09-18T19:22:28.213 回答
1

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

于 2008-09-18T19:23:20.037 回答
1

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

于 2008-09-18T19:24:35.383 回答
0

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

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

于 2008-09-18T19:24:34.760 回答
0

是的,可以将委托视为具有一种方法的接口。

于 2008-09-18T19:26:03.993 回答
0

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

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

对于这个经典问题的一些见解,以及为什么代表是可取的阅读this然后this

于 2008-09-18T19:41:00.213 回答
0

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

于 2009-03-05T14:48:13.853 回答