C# 代理如何链接到事件?

C# 代理如何链接到事件?,c#,events,delegates,C#,Events,Delegates,我读过很多关于代表和事件的材料和例子,但我真的很难理解C#中的事件。我知道委托实际上是方法指针,您可以添加方法,然后在调用委托时一起执行,前提是它符合委托的输入参数和返回类型 (我非常清楚事件是在堆栈溢出上解释的,但这并不能帮助我理解) 我将分享我的代码,它正在工作,但我不明白 namespace Delegates2 { class Program { static void Main(string[] args) { Car mazda = n

我读过很多关于代表和事件的材料和例子,但我真的很难理解C#中的事件。我知道委托实际上是方法指针,您可以添加方法,然后在调用委托时一起执行,前提是它符合委托的输入参数和返回类型

(我非常清楚事件是在堆栈溢出上解释的,但这并不能帮助我理解)

我将分享我的代码,它正在工作,但我不明白

namespace Delegates2 {
    class Program {
        static void Main(string[] args) {
            Car mazda = new Car("Mazda");
            Person chris = new Person();
            mazda.Drive += chris.OnPersonDrive;
            mazda.StartJourney();
            Console.ReadKey();
        }

    }
    public delegate void DriverCarEventHandler(object obj, EventArgs e);
    public class Car
    {
        public string Name { get; }
        public event DriverCarEventHandler Drive;    

        public Car(string name) {
            Name = name;
        }
        public void StartJourney() {
            OnDrive();
        }
        protected virtual void OnDrive() {
            if (Drive != null) {
                Drive(this, EventArgs.Empty);
            }
        }
    }

    public class Person
    {
        public void OnPersonDrive(Object source, EventArgs e) {
            Console.WriteLine("Driving....");
        } 
    }
} 
这里是我所有的困惑点

  • 委托声明中的“Object obj”和“EventArgs e”是什么 代表?对于学习来说,这些似乎常常是空的。哪些地方可能需要不同的示例
  • 基于委托创建事件时 事件现在存储所有指向方法的指针,还是仍然是 代表?我听说过有关向网络添加订户的术语 事件这些“订阅者”方法是否与您的方法相同 向委托添加方法
  • 显然,OnDrive()方法正在“引发”事件。“引发”事件与执行事件相同吗 事件那么,执行所有附加到事件的订阅服务器
  • 为什么当你提出一个事件时,它必须符合 委托输入参数?(这是EventArgs.Empty)。这不是最棒的吗 仅需要匹配此格式的订阅服务器

尽可能简短地回答您的问题,避免让您的问题“过于宽泛”

•委托声明中的“Object obj”和“EventArgs e”代表什么?对于学习来说,这些似乎常常是空的。哪些地方可能需要不同的示例

obj
应始终为非空,并应设置为引发事件的对象的引用
e
应该是
EventArgs
或派生类的实例,包含与事件相关的信息

需要注意的是,这种模式是严格传统的。即,不由任何人强制执行,也不需要。C#
事件
可以使用任何委托类型。
EventHandler
委托类型只是.NET中实现事件的标准方法的基础

•当您基于委托创建事件时,该事件现在是存储所有指向方法的指针还是仍然是委托?我听说过有关向活动添加订户的术语。这些“订阅者”方法是否与您向委托添加方法的方式相同

大多数事件由编译器隐式实现。但重要的是要了解,当您使用
事件
关键字时,您同时声明了事件的
添加
删除
方法。这些方法类似于属性的
get
set
方法。默认实现只需获取传入的委托实例,并分别为
add
remove
方法将其附加到事件的支持字段(也隐式为您生成)的现有值中或从中移除

事件的默认实现将其存储在一个简单的
delegate
type字段中。有些事件的实现更为复杂,例如将事件处理程序引用放入字典中,或者使用弱引用

•显然,OnDrive()方法正在“引发”事件。“引发”事件与执行事件相同吗?那么,执行所有附加到事件的订阅服务器

是的,引发事件只是调用添加(订阅)到事件的委托的问题。NET委托类型都是“多播”委托,因此单个委托实例可以表示多个调用目标。调用一个委托实例将自动调用所有单个调用目标

按照惯例,名为
OnXXX()
的方法(其中
XXX
是某个事件的名称)将始终引发该事件。但没有要求这样做。一个明显的例外是当事件字段为
null
时,即没有投手订阅事件。在这种情况下,显然不会引发事件。另一个更具体的真实示例是Winforms API中的
控件
对象公开的各种事件,这些事件对规则有一些例外(对于与视觉状态更改有关的事件,如当前字体、背景颜色、启用状态等),缩短事件引发逻辑,如果对象或其任何祖先对象(即父母、祖父母等)正在被处置,则返回而不引发事件

•为什么在引发事件时必须符合代表输入参数?(这是EventArgs.Empty)。不是只有订阅者需要匹配这种格式吗

要调用委托,代码必须向其传递必要的参数,就像调用向其传递必要参数所需的任何方法一样(即使存在默认值,编译器也会生成确保提供所有参数值所需的代码)


如果委托的调用方没有传递参数值,那么最终传递给目标方法的值从何而来?

“我知道委托实际上是方法指针,您可以添加方法,然后在调用委托时一起执行”——这正是事件的含义。它们是从对象中公开的委托,您可以向其添加方法指针,当对象本身希望提升它们时,这些方法指针将被执行。委托和事件之间的主要区别在于,事件只能由保存它们的类引发(执行),委托可以由任何代码执行