C# 为什么活动需要代表?为什么我们甚至需要活动?

C# 为什么活动需要代表?为什么我们甚至需要活动?,c#,wpf,winforms,C#,Wpf,Winforms,在过去的几周里,我对一些事件感到困惑。我了解学员是如何工作的,不是它是如何详细工作的,而是足以了解这一点的 委托数据类型是单个强制转换委托。 delegate void是一个多播委托-对方法的引用列表 我知道委托类型编译为类,但不幸的是,我仍然不确定该方法是如何引用的。比如说 delegate void TestDelegate(); TestDelegate testDelegate = new TestDelegate(myObject.SomeMethod) ; 问题1:我认为myObj

在过去的几周里,我对一些事件感到困惑。我了解学员是如何工作的,不是它是如何详细工作的,而是足以了解这一点的
委托数据类型
是单个强制转换委托。
delegate void
是一个多播委托-对方法的引用列表

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

delegate void TestDelegate();
TestDelegate testDelegate = new TestDelegate(myObject.SomeMethod) ;
问题1:我认为myObject是目标,SomeMethod是要引用的方法,但我只传递一个输入。 那么myObject.SomeMethod是否编译成字符串,字符串是否按句点分割?我知道这很荒谬

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

multicastdelegate+=newmethodtobereference
multicastdelegate() ;
调用列表中的每个方法都被调用或通知? 如果这是真的,为什么我需要事件或事件关键字?这仅仅是为了告诉开发人员,嘿,这是一个事件吗?因为我非常困惑,我只想在这个阶段继续,哈哈。这是我今天编写的一个示例代码,用于测试我是否需要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 IsEventNumberEventHandler IsEventNumberEvent没有区别。
请给我解释一下,好让一个傻瓜明白谢谢

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

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

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

否,
myObject。SomeMethod
是一个方法组。这种创建委托实例的方法需要一些编译器的魔力

multicastdelegate+=newmethodtobereference

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


现在谈谈你的主要问题:活动的目的是什么

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

属性是两种方法的组合:
get
set


事件是两个公共方法的组合
subscribe
unsubscribe
,对于类似于字段的事件,它还类似于私有getter。

事件是委托的访问器,就像属性是字段的访问器一样。在目标基本相同的情况下,它可以防止其他代码干扰委托对象。比如,当一堆你不知道的代码订阅了回调时,将其设置为null。事件将访问权限限制为仅添加和删除带有+=和-=运算符的事件处理程序,外部代码根本无法访问私有委托对象


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

添加行的可能重复项
IsEventNumberFound.IsEventNumberRevent=null现在用
事件
关键字试试。@BenVoigt它们都会抛出异常吗?如果是这样,为什么我的编译器会抱怨不一致的不可访问性?属性可访问性不依赖于它们引用的字段,但似乎事件是。。weird@LewsTherin:属性可访问性需要与属性的类型一致。事件也是如此。“还有田野。”本沃伊特,我想我明白你的意思了。如果字符串是私有的,那么返回字符串的属性也需要是私有的?好吧,如果它必须公开,就像活动必须公开一样。。HansPassant所说的“它防止其他代码干扰委托对象”是什么意思?我认为这意味着更改委托的签名。。显然不是。@Lews:type
System.String
是公共的,因此您可以使用该类型的公共属性。但是创建自己的类类型,
MyInternalType
,您可以有私有和内部字段、内部属性等,但不能有公共字段或具有该类型的属性。@BenVoigt那么在这种情况下事件表示的字段是什么?对不起,但是
myObject.SomeMethod
中的方法组是什么“它创建了一个调用多个方法的新委托“我从来没有这样想过。想象一下,一个委托是指向其他委托列表的指针,它可以作为指向其他委托列表的指针。。我的天啊,太复杂了。代表是不变的。我认为内部有针对单播委托的优化,以及针对多播委托的数组,但所有委托类型都源自
multicast delegate