正确声明回调事件处理程序

本文关键字:事件处理 程序 回调 声明 | 更新日期: 2023-09-27 17:52:38

我有一个简单的委托,事件和属性允许我创建回调订阅事件:

public static class Test
{
    /// <summary>Delegate for property changed event</summary>
    public delegate void TestEventHandler();
    /// <summary>Event called when value is changed</summary>
    public static event TestEventHandler OnTestHappening;
    /// <summary>Property to specify our test is happening</summary>
    private static bool testHappening;
    public static bool TestHappening
    {
        get
        {
            return testHappening;
        }
        set
        {
            testHappening = value;
            // Notify our value has changed only if True
            // ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
            if ( value )
            {
                if ( OnTestHappening != null )
                    OnTestHappening();
            }
        }
    }
}

然后我可以很容易地订阅和取消订阅事件,并根据需要触发事件回调:

public class Tester
{
    private void Main()
    {
        Testing();
        // Start the test
        Test.TestHappening = true;
    }
    private void Testing()
    {
        // Unsubscribe from event
        Test.OnTestHappening -= Testing;
        // Check if we're busy testing yet
        if ( !Test.TestHappening )
        {
            // Subscribe to event
            Test.OnTestHappening += new Test.TestEventHandler( Testing );
            return;
        }
        // Do stuff here....
    }
}

编译时,代码分析给了我,"CA1009:正确声明事件处理程序?",我搜索了很多问题,文章等,但没有一个感觉他们解决了我的场景。我似乎找不到转换的具体起点,我开始怀疑我是否意味着完全重写实现?

编辑:首先,我真的很感谢你的帮助,在发表这篇文章之前,我确实仔细地浏览了所有的网站,我确实看到了(并尝试使用)你们所有人发布的每个链接。我甚至回去重新研究委托和事件但我觉得我不知怎么错过了起点因为每次我试图改变它的一部分,我只是不断地产生错误,我不能回来,像:
public delegate void TestEventHandler( object sender, EventArgs e );

在我访问的其他链接中,我只能找到一个与我的代码相似的地方(无论是在委托,处理程序还是属性中),但找不到任何与我的代码足够相关的东西来真正注入"eureka"时刻

编辑2:我现在用"看起来"是正确的标准重建了我的例子,但这段代码是如此丑陋,看起来就像用一根confogulus棍子打了一顿,在被油炸之前浸入了一罐争议:

public static class Test
{
    /// <summary>Delegate for property changed event</summary>
    public delegate void TestEventHandler( object sender, EventArgs e );
    /// <summary>Event called when value is changed</summary>
    public static event TestEventHandler OnTestHappening;
    /// <summary>Property to specify our test is happening</summary>
    private static bool testHappening;
    public static bool TestHappening
    {
        get
        {
            return testHappening;
        }
        set
        {
            testHappening = value;
            // Notify our value has changed only if True
            // ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
            if ( value )
            {
                if ( OnTestHappening != null )
                    OnTestHappening( null, EventArgs.Empty );
            }
        }
    }
}
public class Tester
{
    private void Main()
    {
        Testing( this, EventArgs.Empty );
        // Start the test
        Test.TestHappening = true;
    }
    private void Testing( object sender, EventArgs e )
    {
        // Unsubscribe from the event
        Test.OnTestHappening -= Testing;
        // Check if we're busy testing yet
        if ( !GlobalClass.SystemOnline )
        {
            // Subscribe to the event
            Test.OnTestHappening += new Test.TestEventHandler( Testing );
            return;
        }
        // Do stuff here....
    }
}

请告诉我我错过了什么,实际上有一个更优雅的实现

编辑3:基于Enigmativity的代码,我将代码重新设计为最基本的形式。我还在不同的方法中移动了将变量设置为true的代码,因此它在Main中看起来并不那么愚蠢。

public static class Test4
{
    /// <summary>Event called when value is changed</summary>
    public static event EventHandler TestHappening;
    /// <summary>Property to specify our test is happening</summary>
    private static bool test = false;
    public static bool Test
    {
        get
        {
            return test;
        }
        set
        {
            // Notify our value has changed only if True
            // ie. Only fire an event when we're ready as we'll hook methods to the Event that must only fire if ready
            if ( value )
            {
                TestHappening( null, EventArgs.Empty );
            }
        }
    }
}
public class Tester4
{
    private void Main()
    {
        Testing( this, EventArgs.Empty );
    }
    private void Testing( object sender, EventArgs e )
    {
        // Unsubscribe from the event
        Test4.TestHappening -= Testing;
        // Check if we're busy testing yet
        if ( !Test4.Test )
        {
            // Subscribe to the event
            Test4.TestHappening += Testing;
            return;
        }
        // Do stuff here....
    }
    private void SomeMethodCalledFromSomewhere()
    {
        // Set the value to true and thereby start the test
        Test4.Test = true;
    }
}
  1. 这将被认为是好的代码,或者我应该宁愿有OnTestHappening方法定义在Enigmativity的代码?
  2. 为什么我不能使用无参数委托?它现在使用默认的( object sender, EventArgs e ),但感觉过度,没有意义,为什么编译器是满意的,但根据编码标准,它被认为是坏的代码?我不是在争论标准,而是试图理解它的推理。

正确声明回调事件处理程序

根据Storm的要求,以下是我最有可能构建代码的方式。它更符合标准约定。

public static class TestClass
{
    public delegate void TestEventHandler(object sender, EventArgs e);
    public static event TestEventHandler TestHappening;
    private static bool test = false;
    public static bool Test
    {
        get
        {
            return test;
        }
        set
        {
            test = value;
            if (test)
            {
                OnTestHappening();
            }
        }
    }
    private static void OnTestHappening()
    {
        var handler = TestHappening;
        if (handler != null)
            handler(null, EventArgs.Empty);
    }
}

Tester看起来像这样:

public class Tester
{
    public void Main()
    {
        TestClass.TestHappening += Testing;
        Go();
    }
    private void Testing(object sender, EventArgs e)
    {
        Console.WriteLine(TestClass.Test);
        TestClass.TestHappening -= Testing;
    }
    private void Go()
    {
        TestClass.Test = true;
    }
}

调用它会像这样:

var tester = new Tester();
tester.Main();

运行此命令将True输出到控制台。


如果我用一种更标准的方式来写,它看起来应该是这样的:

public class TestEventArg : EventArgs
{
    public TestEventArg(bool updatedValue)
    {
        this.UpdatedValue = updatedValue;
    }
    public bool UpdatedValue { get; private set; }
}
public class TestClass
{
    public event EventHandler<TestEventArg> TestHappening;
    private bool test = false;
    public bool Test
    {
        get { return test; }
        set
        {
            var old = test;
            test = value;
            if (test != old)
                OnTestHappening(test);
        }
    }
    private void OnTestHappening(bool updatedValue)
    {
        var handler = TestHappening;
        if (handler != null)
            handler(this, new TestEventArg(updatedValue));
    }
}