我会失去,放弃.NET中的标准事件处理程序的模式是什么? [英] What would I lose by abandoning the standard EventHandler pattern in .NET?

查看:93
本文介绍了我会失去,放弃.NET中的标准事件处理程序的模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有对.NET中的事件的标准模式 - 他们用委托类型,需要一个普通的对象调用发送者,然后实际的有效载荷的第二个参数,这应该从 EventArgs的得到。

There's a standard pattern for events in .NET - they use a delegate type that takes a plain object called sender and then the actual "payload" in a second parameter, which should be derived from EventArgs.

第二个参数的基本原理,从正在导出EventArgs的似乎非常清楚(见 .NET框架标准库注释的参考)。它的目的是确保事件汇和源作为软件的发展之间的二进制兼容性。对于每一个事件,即使只有一个参数,我们推​​导出具有包含这样的说法单个属性自定义事件参数类,这样一来,我们保留添加更多的特性在未来的版本有效载荷不破坏现有的客户端代码的能力。在自主开发的组件组成的生态系统非常重要的。

The rationale for the second parameter being derived from EventArgs seems pretty clear (see the .NET Framework Standard Library Annotated Reference). It is intended to ensure binary compatibility between event sinks and sources as the software evolves. For every event, even if it only has one argument, we derive a custom event arguments class that has a single property containing that argument, so that way we retain the ability to add more properties to the payload in future versions without breaking existing client code. Very important in an ecosystem of independently-developed components.

不过,我发现,同样适用于零参数。这意味着,如果我有了我的第一个版本没有参数的事件,而我写的:

But I find that the same goes for zero arguments. This means that if I have an event that has no arguments in my first version, and I write:

public event EventHandler Click;



...然后我做错了。如果我在未来改变委托类型到一个新的类作为其有效载荷:

... then I'm doing it wrong. If I change the delegate type in the future to a new class as its payload:

public class ClickEventArgs : EventArgs { ...

...我将打破与我的客户二进制兼容性。客户最终绑定到一个内部方法 add_Click 这需要事件处理程序的具体超载,如果我改变委托类型,然后他们无法找到过载,所以有一个 MissingMethodException

... I will break binary compatibility with my clients. The client ends up bound to a specific overload of an internal method add_Click that takes EventHandler, and if I change the delegate type then they can't find that overload, so there's a MissingMethodException.

好吧,如果我用什么方便的通用版本

Okay, so what if I use the handy generic version?

public EventHandler<EventArgs> Click;

没有,还是错的,因为事件处理程序和LT; ClickEventArgs> 不是事件处理程序和LT; EventArgs的方式>

No, still wrong, because an EventHandler<ClickEventArgs> is not an EventHandler<EventArgs>.

因此,要获得的利益 EventArgs的,您有无的从它派生,而不是直接使用原样。如果不这样做,你可能也不会使用它(在我看来)。

So to get the benefit of EventArgs, you have to derive from it, rather than using it directly as is. If you don't, you may as well not be using it (it seems to me).

然后是第一个参数,发件人。在我看来,像邪恶耦合的食谱。一个事件触发本质上是一个函数调用。应的功能,一般来说,要挖回通过堆栈,并找出谁在打电话的是,并相应地调整其行为的能力?我们是否应该强制要求的接口应该是这样的?

Then there's the first argument, sender. It seems to me like a recipe for unholy coupling. An event firing is essentially a function call. Should the function, generally speaking, have the ability to dig back through the stack and find out who the caller was, and adjust its behaviour accordingly? Should we mandate that interfaces should look like this?

public interface IFoo
{
    void Bar(object caller, int actualArg1, ...);
}



毕竟,酒吧的实现者可能想知道谁是主叫是,这样他们就可以查询其他信息!我希望你现在呕吐。它为什么要对事件有什么不同?

After all, the implementor of Bar might want to know who the caller was, so they can query for additional information! I hope you're puking by now. Why should it be any different for events?

所以,即使我准备把制作独立的痛 EventArgs的为每一位我宣布事件派生类,只是为了它的价值,而使用我的 EventArgs的可言,我肯定宁愿放下对象发件人的说法。

So even if I am prepared to take the pain of making a standalone EventArgs-derived class for every event I declare, just to make it worth my while using EventArgs at all, I definitely would prefer to drop the object sender argument.

Visual Studio的自动完成功能似乎并不关心你用什么代表一个事件 - 你可以键入 + = [按空格键,回车] 的,它给你,无论代表它发生的比赛是写一个处理方法。

Visual Studio's autocompletion feature doesn't seem to care what delegate you use for an event - you can type += [hit Space, Return] and it writes a handler method for you that matches whatever delegate it happens to be.

所以,我会失去什么价值由从标准模式偏差?

So what value would I lose by deviating from the standard pattern?

作为奖励的问题,将C#/ CLR 4.0做任何事情来改变这一状况,可能通过在代表逆变?我试图探讨这一点,但命中另一个问题。我原先包括在其他问题的问题的这个方面,但它引起那里的混乱。这似乎有点多分裂这一成一共有三个问题...

As a bonus question, will C#/CLR 4.0 do anything to change this, perhaps via contravariance in delegates? I attempted to investigate this but hit another problem. I originally included this aspect of the question in that other question, but it caused confusion there. And it seems a bit much to split this up into a total of three questions...

更新:

原来我是正确的怀疑逆变对这一整个问题的影响。

Turns out I was right to wonder about the effects of contravariance on this whole issue!

作为的 stackoverflow.com/questions/1120688/\">noted~~V,新的编译器规则,留在在运行时炸毁类型系统一个洞。该洞已有效地堵塞通过定义事件处理程序< T> 不同,以动作< T>

因此,对于事件,以避免你不应该使用这种类型的孔动作< T> 。这并不意味着你必须使用事件处理程序和LT; TEventArgs> ;它只是意味着,如果你使用一个通用的委托类型,不挑人是为逆变启用。

So for events, to avoid that type hole you should not use Action<T>. That doesn't mean you have to use EventHandler<TEventArgs>; it just means that if you use a generic delegate type, don't pick one that is enabled for contravariance.

推荐答案

没什么,你失去什么。我一直在使用动作<> ,因为.NET 3.5走了出来,这是更为自然,更容易对程序

Nothing, you lose nothing. I've been using Action<> since .NET 3.5 came out and it is far more natural and easier to program against.

我甚至不处理的事件处理程序键入生成的事件处理程序了,简单的写你想要的方法签名,并将其连接了一个拉姆达:

I don't even deal with the EventHandler type for generated event handlers anymore, simply write the method signature you want and wire it up with a lambda:

btnCompleteOrder.OnClick += (o,e) => _presenter.CompleteOrder();

这篇关于我会失去,放弃.NET中的标准事件处理程序的模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆