【问题标题】:Why do Events need Delegates? Why do we even Need Events?为什么活动需要代表?为什么我们甚至需要事件?
【发布时间】:2012-05-27 16:33:09
【问题描述】:

过去几周我一直对事件感到困惑。我了解代表的工作方式,而不是详细的工作方式,但足以知道 delegate datatype 是一个单一的演员代表。 delegate void 是一个多播委托 - 对方法的引用列表。

我知道委托类型编译为一个类,但不幸的是我仍然不确定该方法是如何被引用的。例如

delegate void TestDelegate();
TestDelegate testDelegate = new TestDelegate(myObject.SomeMethod) ;

问题 1:我认为 myObject 是目标,SomeMethod 是要引用的方法,但我只传递了一个输​​入。 那么 myObject.SomeMethod 是否编译为字符串,字符串是否按句点拆分?可笑我知道。

问题 2: 当您添加到多播委托时

multicastdelegate+=newmethodtobereference
multicastdelegate() ;

调用列表中的每个方法都被调用或通知? 如果这是真的,为什么我需要事件或 event 关键字地狱?只是简单的告诉开发者,嘿,这是在充当事件吗?因为我很困惑,我只想在这个阶段继续前进,哈哈。这是我今天写的一个示例代码,用于测试是否需要 event 关键字。

using System;
namespace LambdasETs
{
    public delegate void IsEvenNumberEventHandler(int numberThatIsEven);

    public class IsEvenNumberFound
    {
        public  IsEvenNumberEventHandler IsEvenNumberEvent;
        private int number;

        public void InputNumber(int n)
        {
            if(number %2 ==0)
            {
                if (IsEvenNumberEvent != null)
                {
                    IsEvenNumberEvent(n);
                }
            }
        }


        public static void Main()
        {
            IsEvenNumberFound isEvenNumberFound = new IsEvenNumberFound();

            isEvenNumberFound.IsEvenNumberEvent += IsEvenNumberAction;

             isEvenNumberFound.InputNumber(10);

            Console.ReadLine();

        }

        public static void IsEvenNumberAction(int number)
        {
            Console.WriteLine("{0} is an even number!", number);
        }
    }


}

public IsEvenNumberEventHandler IsEvenNumberEvent;字段中添加event关键字没有区别。 请各位大侠解释一下,让菜鸟看得懂,谢谢。

【问题讨论】:

标签: c# wpf winforms


【解决方案1】:

事件是委托的访问器,就像属性是字段的访问器一样。具有大致相同的目标,它可以防止其他代码与委托对象混淆。就像当一堆您不知道的代码订阅了回调时将其设置为 null 一样。事件将访问限制为只能使用 += 和 -= 运算符添加和删除事件处理程序,外部代码根本无法访问私有委托对象。

并使用add and remove accessors 自定义订阅。您不经常这样做,因为您通常对编译器生成的默认访问器感到满意。包括一个存储委托的隐藏支持字段。但例如在框架代码中并不少见。与 System.Windows.Forms.Control 支持的许多事件的所有事件处理程序一样,它们都存储在单个 EventHandlerList 中。或 WPF 等效项 EventHandlersStore。

【讨论】:

  • 如果这是真的,为什么我的编译器会抱怨不一致的不可访问性?属性可访问性不依赖于它们引用的字段,但似乎事件......很奇怪
  • @LewsTherin:属性可访问性需要与属性的类型保持一致。与事件相同。和字段。
  • @BenVoigt 我想我明白你的意思了。如果字符串是私有的,那么返回字符串的属性也需要私有?好吧,如果它必须像事件一样公开.. HansPassant 的意思是“它可以防止其他代码与委托对象混淆”我认为这意味着更改委托的签名.. 显然不是。
  • @Lews:System.String 类型是公共的,因此您可以拥有该类型的公共属性。但是创建你自己的类类型MyInternalType,你可以拥有私有和内部字段、内部属性等,但不能拥有该类型的公共字段或属性。
  • @BenVoigt 那么在这种情况下,事件代表的字段是什么?
【解决方案2】:

但足以知道委托数据类型是单个强制转换委托。 delegate void 是一个多播委托 - 方法的引用列表。

不正确。所有“普通”委托都是多播的,即使它们具有非 void 返回类型。

问题 1:我认为 myObject 是目标,SomeMethod 是要引用的方法,但我只传递了一个输​​入。那么 myObject.SomeMethod 是否编译为字符串,字符串是否按句点拆分?我知道这很荒谬。

不,myObject.SomeMethod 是一个方法组。这种创建委托实例的方式涉及到一点编译器的魔力。

multicastdelegate+=newmethodtobereference

如果multicastdelegate 是一个普通的委托变量,这相当于multicastdelegate = multicastdelegate + newmethodtobereference,即它创建一个调用多个方法的新委托,并将其分配给multicastdelegate


现在是您的主要问题:活动的目的是什么?

事件具有委托类型。它们的行为类似于属性。它们的目的是封装,特别是它们只允许消费者订阅(+=)和取消订阅(-=),但不能读取事件的值。

属性是两种方法的组合:getset

事件是两个公共方法subscribeunsubscribe 的组合,在类字段事件的情况下也类似于私有getter。

【讨论】:

  • 抱歉,myObject.SomeMethod 中的方法组是什么?“它创建了一个调用多个方法的新委托”我从来没有这样想过。想象一下,它是否就像一个代表是一个指向其他代表列表的指针,它可以充当指向其他代表列表的指针......我的上帝,多么令人费解。
  • 委托是不可变的。我认为在内部有针对单次转换委托的优化,以及针对多路转换委托的数组,但所有委托类型都派生自 MultiCastDelegate
猜你喜欢
  • 2010-09-20
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2019-06-09
  • 2016-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多