<bdo id='abxhr'></bdo><ul id='abxhr'></ul>

    <small id='abxhr'></small><noframes id='abxhr'>

    1. <tfoot id='abxhr'></tfoot>
      <i id='abxhr'><tr id='abxhr'><dt id='abxhr'><q id='abxhr'><span id='abxhr'><b id='abxhr'><form id='abxhr'><ins id='abxhr'></ins><ul id='abxhr'></ul><sub id='abxhr'></sub></form><legend id='abxhr'></legend><bdo id='abxhr'><pre id='abxhr'><center id='abxhr'></center></pre></bdo></b><th id='abxhr'></th></span></q></dt></tr></i><div id='abxhr'><tfoot id='abxhr'></tfoot><dl id='abxhr'><fieldset id='abxhr'></fieldset></dl></div>

    2. <legend id='abxhr'><style id='abxhr'><dir id='abxhr'><q id='abxhr'></q></dir></style></legend>

    3. 使用扩展方法引发 C# 事件 - 这很糟糕吗?

      Raising C# events with an extension method - is it bad?(使用扩展方法引发 C# 事件 - 这很糟糕吗?)
    4. <small id='j2WOc'></small><noframes id='j2WOc'>

        <tfoot id='j2WOc'></tfoot>
          <bdo id='j2WOc'></bdo><ul id='j2WOc'></ul>

          • <legend id='j2WOc'><style id='j2WOc'><dir id='j2WOc'><q id='j2WOc'></q></dir></style></legend>

              <tbody id='j2WOc'></tbody>

            1. <i id='j2WOc'><tr id='j2WOc'><dt id='j2WOc'><q id='j2WOc'><span id='j2WOc'><b id='j2WOc'><form id='j2WOc'><ins id='j2WOc'></ins><ul id='j2WOc'></ul><sub id='j2WOc'></sub></form><legend id='j2WOc'></legend><bdo id='j2WOc'><pre id='j2WOc'><center id='j2WOc'></center></pre></bdo></b><th id='j2WOc'></th></span></q></dt></tr></i><div id='j2WOc'><tfoot id='j2WOc'></tfoot><dl id='j2WOc'><fieldset id='j2WOc'></fieldset></dl></div>

                本文介绍了使用扩展方法引发 C# 事件 - 这很糟糕吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我们都熟悉 C# 事件声明的可怕之处.为了确保线程安全,标准是这样写:

                We're all familiar with the horror that is C# event declaration. To ensure thread-safety, the standard is to write something like this:

                public event EventHandler SomethingHappened;
                protected virtual void OnSomethingHappened(EventArgs e)
                {            
                    var handler = SomethingHappened;
                    if (handler != null)
                        handler(this, e);
                }
                

                最近在这个板上的一些其他问题(我现在找不到)中,有人指出在这种情况下可以很好地使用扩展方法.这是一种方法:

                Recently in some other question on this board (which I can't find now), someone pointed out that extension methods could be used nicely in this scenario. Here's one way to do it:

                static public class EventExtensions
                {
                    static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
                    {
                        var handler = @event;
                        if (handler != null)
                            handler(sender, e);
                    }
                    static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
                        where T : EventArgs
                    {
                        var handler = @event;
                        if (handler != null)
                            handler(sender, e);
                    }
                }
                

                有了这些扩展方法,你需要声明和引发一个事件是这样的:

                With these extension methods in place, all you need to declare and raise an event is something like this:

                public event EventHandler SomethingHappened;
                
                void SomeMethod()
                {
                    this.SomethingHappened.RaiseEvent(this, EventArgs.Empty);
                }
                

                我的问题:这是个好主意吗?我们是否因为没有标准的 On 方法而遗漏了什么?(我注意到的一件事是它不适用于具有显式添加/删除代码的事件.)

                My question: Is this a good idea? Are we missing anything by not having the standard On method? (One thing I notice is that it doesn't work with events that have explicit add/remove code.)

                推荐答案

                它仍然适用于具有显式添加/删除的事件 - 您只需要使用委托变量(或者您已经存储了委托)事件名称.

                It will still work with events that have an explicit add/remove - you just need to use the delegate variable (or however you've stored the delegate) instead of the event name.

                但是,有一种更简单的方法可以使其成为线程安全的 - 使用无操作处理程序对其进行初始化:

                However, there's an easier way to make it thread-safe - initialize it with a no-op handler:

                public event EventHandler SomethingHappened = delegate {};
                

                调用额外委托对性能的影响可以忽略不计,而且它确实使代码更容易.

                The performance hit of calling an extra delegate will be negligible, and it sure makes the code easier.

                顺便说一句,在您的扩展方法中,您不需要额外的局部变量 - 您可以这样做:

                By the way, in your extension method you don't need an extra local variable - you could just do:

                static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
                {
                    if (@event != null)
                        @event(sender, e);
                }
                
                static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
                    where T : EventArgs
                {
                    if (@event != null)
                        @event(sender, e);
                }
                

                我个人不会使用关键字作为参数名称,但它并没有真正改变调用方,所以你可以做你想做的:)

                Personally I wouldn't use a keyword as a parameter name, but it doesn't really change the calling side at all, so do what you want :)

                至于OnXXX"方法:您是否计划派生您的类?在我看来,大多数课程都应该是密封的.如果您这样做,您是否希望这些派生类能够引发事件?如果这两个问题的答案是否",那么不要打扰.如果两者的答案都是是",那么就这样做:)

                As for the "OnXXX" method: are you planning on your classes being derived from? In my view, most classes should be sealed. If you do, do you want those derived classes to be able to raise the event? If the answer to either of these questions is "no" then don't bother. If the answer to both is "yes" then do :)

                这篇关于使用扩展方法引发 C# 事件 - 这很糟糕吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                C# namespace alias - what#39;s the point?(C# 命名空间别名 - 有什么意义?)
                Using Xpath With Default Namespace in C#(在 C# 中使用具有默认命名空间的 Xpath)
                IBM.Data.DB2.Core connection problems(IBM.Data.DB2.Core 连接问题)
                Generating an EDMX from a DB2 Database(从 DB2 数据库生成 EDMX)
                Datetime field overflow with IBM Data Server Client v9.7fp5(IBM Data Server Client v9.7fp5 的日期时间字段溢出)
                Using entity Framework with .NET Core and DB2(将实体框架与 .NET Core 和 DB2 结合使用)

                    <tbody id='r5IeS'></tbody>

                        <bdo id='r5IeS'></bdo><ul id='r5IeS'></ul>
                        <legend id='r5IeS'><style id='r5IeS'><dir id='r5IeS'><q id='r5IeS'></q></dir></style></legend>
                        <tfoot id='r5IeS'></tfoot>

                          <i id='r5IeS'><tr id='r5IeS'><dt id='r5IeS'><q id='r5IeS'><span id='r5IeS'><b id='r5IeS'><form id='r5IeS'><ins id='r5IeS'></ins><ul id='r5IeS'></ul><sub id='r5IeS'></sub></form><legend id='r5IeS'></legend><bdo id='r5IeS'><pre id='r5IeS'><center id='r5IeS'></center></pre></bdo></b><th id='r5IeS'></th></span></q></dt></tr></i><div id='r5IeS'><tfoot id='r5IeS'></tfoot><dl id='r5IeS'><fieldset id='r5IeS'></fieldset></dl></div>
                        1. <small id='r5IeS'></small><noframes id='r5IeS'>