假设我们有:
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。
除了获得更短的代码外,代表们的真正好处是什么?
答案 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)”委托并在任何实现它的类上调用它。
答案 9 :(得分:0)
至少有一个向Java添加闭包(即匿名委托)的提议,它们等同于具有单个成员方法的接口。