首先,好问题。我钦佩您对实用程序的关注,而不是一味地接受“最佳实践”。+1。
我之前已经阅读过该指南。您必须记住一些有关它的内容-它只是一个指南,主要供那些知道如何编程但对C#的工作方式不太熟悉的C#新手使用。它不只是规则页面,而是描述通常已经完成的事情的页面。由于他们已经在任何地方都采用这种方法,因此保持一致可能是一个好主意。
我会回答你的问题。
首先,我假设您已经知道接口是什么。对于委托,可以说它是一个结构,其中包含指向方法的类型化指针,以及指向表示该this
方法参数的对象的可选指针。对于静态方法,后一个指针为null。
也有一些组播委托,它们与委托一样,但是可能会为其分配多个结构(这意味着对组播委托的Invoke的单个调用将调用其分配的调用列表中的所有方法)。
事件设计模式意味着什么?
它们的意思是在C#中使用事件(该事件具有特殊的关键字,可以巧妙地实现这种极其有用的模式)。多播委托推动了C#中的事件。
当您定义事件时,例如在此示例中:
class MyClass {
// Note: EventHandler is just a multicast delegate,
// that returns void and accepts (object sender, EventArgs e)!
public event EventHandler MyEvent;
public void DoSomethingThatTriggersMyEvent() {
// ... some code
var handler = MyEvent;
if (handler != null)
handler(this, EventArgs.Empty);
// ... some other code
}
}
编译器实际上将其转换为以下代码:
class MyClass {
private EventHandler MyEvent = null;
public void add_MyEvent(EventHandler value) {
MyEvent += value;
}
public void remove_MyEvent(EventHandler value) {
MyEvent -= value;
}
public void DoSomethingThatTriggersMyEvent() {
// ... some code
var handler = MyEvent;
if (handler != null)
handler(this, EventArgs.Empty);
// ... some other code
}
}
然后,您通过以下方式订阅活动
MyClass instance = new MyClass();
instance.MyEvent += SomeMethodInMyClass;
编译成
MyClass instance = new MyClass();
instance.add_MyEvent(new EventHandler(SomeMethodInMyClass));
因此,这在C#(或一般.NET)中会发生。
如果使用委托,组成如何变得容易?
这很容易证明:
假设您有一个类,该类依赖于要传递给它的一组操作。您可以将这些操作封装在接口中:
interface RequiredMethods {
void DoX();
int DoY();
};
任何想要将动作传递给您的类的人都必须首先实现该接口。或者,您可以通过以下课程来简化他们的生活:
sealed class RequiredMethods {
public Action DoX;
public Func<int> DoY();
}
这样,调用者只需在运行时创建RequiredMethods实例并将方法绑定到委托即可。通常这比较容易。
在正确的情况下,这种处事方式非常有益。考虑一下-当您真正关心的是将实现传递给您时,为什么要依赖接口?
有一组相关方法时使用接口的好处
使用接口是有益的,因为接口通常需要显式的编译时实现。这意味着您将创建一个新类。
而且,如果您在一个程序包中有一组相关的方法,那么使该程序包可被代码的其他部分重用是有益的。因此,如果他们可以简单地实例化一个类而不是构建一组委托,那将更加容易。
如果一类仅需要一个实现,则使用接口的好处
如前所述,接口是在编译时实现的-这意味着它们比调用委托(这本身就是间接级别)要高效。
“一个实现”可能意味着一个存在一个明确定义的位置的实现。
否则,实现可能来自程序中恰好符合方法签名的任何地方。这样可以提供更大的灵活性,因为方法只需要符合预期的签名,而不必属于显式实现特定接口的类。但是这种灵活性可能要付出一定的代价,并且实际上破坏了Liskov Substitution原则,因为大多数时候您都希望明确,因为这样可以最大程度地减少发生事故的机会。就像静态打字一样。
该术语在这里也可以指多播委托。接口声明的方法只能在实现类中实现一次。但是代表可以累积多个方法,这些方法将被顺序调用。
因此,总的来说,该指南似乎还不足以提供信息,仅能按其本身的功能运行-而不是规则手册。一些建议实际上听起来有点矛盾。由您决定何时才是合适的方法。该指南似乎只给我们提供了一条一般的道路。
希望您的问题得到满意的答复。再一次,对这个问题表示敬意。