C# 引发事件与直接方法调用的区别

C# 引发事件与直接方法调用的区别,c#,C#,引发事件时,将调用其事件处理程序。乙二醇 使用事件机制和直接调用其他方法(例如,如果方法a()中满足条件,则调用B())之间有什么区别 消费活动和募捐活动的区别是什么 谢谢引发事件(或调用链接中的术语)意味着您正在向所有消费者发送事件。例如,当用鼠标单击窗口时,它可以引发事件 消费事件意味着您正在接收和处理来自发送它的人的事件。例如,您可能想知道鼠标单击窗口的时间 如果您只有一个消费者,那么您可以通过直接提供回调来实现类似的功能: // 'Event' type: delegate void D

引发事件时,将调用其事件处理程序。乙二醇

使用事件机制和直接调用其他方法(例如,如果方法a()中满足条件,则调用B())之间有什么区别

消费活动和募捐活动的区别是什么

谢谢

引发事件(或调用链接中的术语)意味着您正在向所有消费者发送事件。例如,当用鼠标单击窗口时,它可以引发事件

消费事件意味着您正在接收和处理来自发送它的人的事件。例如,您可能想知道鼠标单击窗口的时间


如果您只有一个消费者,那么您可以通过直接提供回调来实现类似的功能:

// 'Event' type:
delegate void DelMyEvent();
// consumer:
class Consumer
{
    Producer _theProducer;
    void RegisterForNotification()
    {
       _theProducer.OnMyEvent = new DelMyEvent(OnMyEvent);
    }
    void OnMyEvent() { }
}
// producer:
class Producer
{
   public DelMyEvent OnMyEvent;
   void SendNotification()
   {
      if( OnMyEvent != null ) OnMyEvent();
   }
}
事件机制通过防止使用者直接设置委托值来稍微清理这一点。相反,它使消费者向
+=
操作符注册自己。当第一个使用者注册时,委托被设置,当第二个使用者注册时,他们的两个回调被
delegate.Combine
链接在一起

引发事件时,将调用其事件 处理者

一开始就错了。可能没有事件处理程序。或者很多。你不知道。这是直接调用方法的主要区别。在您最喜欢的设计模式书中查找“观察者模式”

使用 事件机制和直接调用 其他方法(例如,如果条件为 在方法A()中遇到,调用B())

就业务逻辑而言,两者之间没有区别。我的意思是,你可以通过各种方式完成相同的任务。这只是一种不同的方式。真正的区别在于处理其他模块通知所需的工作量

在引发事件时,您实际上是在说“嘿,发生了一些事情。任何一段代码在发生这种情况时已注册以获得通知,请让他们知道。哪些模块得到通知不是我关心的问题,因为我假设(在运行时)所有需要知道的模块都已设置为进行通知。”

通过直接调用每个方法,您决定告诉这个(或这些)模块,并且只告诉这些模块,发生了一些事情。您正在断言,无论这些模块处于什么状态都不重要,它们需要知道发生了什么事件


这两种方法都适用于不同的情况。事件通知更具动态性。不同的模块可以注册和取消注册通知。直接方法调用更静态。某一组对象(或模块等)绝对会被通知(当然例外情况除外),但只有这些对象才会被通知。

除了上述多个/无订阅者场景外,事件还用于减少代码耦合-例如方法A()在编译时不需要知道关于方法B()的任何信息。这样可以更好地分离关注点,减少代码的脆弱性


在野外,您更可能看到框架和UI代码中使用的事件,而在应用程序的域逻辑中,开发人员更经常使用和之类的东西来解耦代码。最近,关于在域逻辑中使用事件,在不同的领域有了更多的讨论,这是一种巧妙命名的方法。

区别在于:

方法调用=“执行此特定操作”

Event raise=“如果有人在倾听和关心,这件事就发生了。”

它是关注点分离和可重用性的核心。如果单击按钮调用特定方法,则该按钮不是可重用组件。但是,如果它只是“宣布”它被点击的程序,并且相关方负责订阅该程序,那么它是无限可重用的


如何实现这一点(通过委托)的底层技术实现是不相关的

对于任何对事件调用性能感兴趣的人,我已经做了这个简单的基准测试。 它显示了直接调用方法、通过接口调用方法、通过委托调用方法和通过事件调用方法(其中附加了一个处理程序)之间的区别

在每个场景中,该方法以相应的方式被调用100万次。以下是(可能令人惊讶的)结果:

代表呼叫:23240毫秒-最快

事件呼叫:23295毫秒

直接电话:23396毫秒

接口调用:23716ms-最慢

这些测量是在发布版本中使用C#in.NET4.0完成的

代码如下:

class Program
{
    static void Main(string[] args)
    {
        TestClass.RunTest();
        Console.ReadLine();
    }
}

interface ITestClass
{
    void TestMethod(object sender, TestEventArgs eventErgs);
}

class TestClass : ITestClass
{
    #region Events

    event EventHandler<TestEventArgs> TestEvent;

    #endregion

    #region Constructor

    public TestClass()
    {
        TestEvent += TestMethod;
    }

    #endregion

    #region Public Methods

    public static void RunTest()
    {
        int testCount = 1000000000; //1 000 000 000

        string format = "{0:### ### ### ##0}";

        #region Direct Call

        Console.WriteLine("Direct call");
        TestClass testClass = new TestClass();

        testClass.TestMethod(testClass, new TestEventArgs(3));

        Stopwatch stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < testCount; ++i)
        {
            testClass.TestMethod(testClass, new TestEventArgs(3));
        }
        stopwatch.Stop();
        Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
        Console.WriteLine();

        #endregion

        #region Interface Call

        Console.WriteLine("Interface call");
        ITestClass itestClass = new TestClass();
        itestClass.TestMethod(testClass, new TestEventArgs(3));

        stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < testCount; ++i)
        {
            itestClass.TestMethod(testClass, new TestEventArgs(3));
        }
        stopwatch.Stop();
        Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
        Console.WriteLine();

        #endregion

        #region Delegate Call

        Console.WriteLine("Delegate call");
        TestClass delegateTestClass = new TestClass();
        Action<object, TestEventArgs> delegateMethod = delegateTestClass.TestMethod;
        delegateMethod(testClass, new TestEventArgs(3));

        stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < testCount; ++i)
        {
            delegateMethod(testClass, new TestEventArgs(3));
        }
        stopwatch.Stop();
        Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
        Console.WriteLine();

        #endregion

        #region Event Call

        Console.WriteLine("Event call");
        TestClass eventTestClast = new TestClass();
        eventTestClast.TestEvent(testClass, new TestEventArgs(3));

        stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < testCount; ++i)
        {
            eventTestClast.TestEvent(testClass, new TestEventArgs(3));
        }
        stopwatch.Stop();
        Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
        Console.WriteLine();

        #endregion
    }

    #endregion

    #region ITestClass Members

    public void TestMethod(object sender, TestEventArgs e)
    {
        e.Result = e.Value * 3;
    }

    #endregion
}

class TestEventArgs : EventArgs
{
    public int Value { get; private set; }

    public int Result { get; set; }

    public TestEventArgs(int value)
    {
        Value = value;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
TestClass.RunTest();
Console.ReadLine();
}
}
接口ITestClass
{
void TestMethod(对象发送方、testEventTargets事件);
}
类TestClass:ITestClass
{
#地区活动
事件处理程序TestEvent;
#端区
#区域构造函数
公共测试类()
{
TestEvent+=TestMethod;
}
#端区
#区域公共方法
公共静态void RunTest()
{
int testCount=100000000;//1 000 000
字符串格式=“{0:############0}”;
#地区直拨电话
控制台。写线(“直接呼叫”);
TestClass TestClass=新的TestClass();
testClass.TestMethod(testClass,新的TestEventTargets(3));
秒表秒表=Stopwatch.StartNew();
对于(int i=0;i