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

Declare callback event handlers correctly

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

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: Declare event handlers correctly?" 我搜索了高低,发现了很多问题、文章等,但 none 感觉它们解决了我的情况。我似乎找不到转换的具体起点,我开始怀疑我是否打算完全重写实现?

编辑:首先,我非常感谢您的帮助,在发布此内容之前,我确实仔细浏览了所有可能的网站,并且确实看到了(并尝试使用)你们发布的每个链接。我什至回去再次研究了代表和事件,但我觉得我以某种方式错过了起点,因为每次我尝试更改它的一部分时,我都会不断产生无法恢复的错误,例如:

public delegate void TestEventHandler( object sender, EventArgs e );

在我访问的其他链接中,我只能找到 1 个与我的代码相似的地方(在委托、处理程序或 属性 中),但找不到任何与我的代码相关的东西灌输那个"eureka"时刻

编辑 2:我现在已经用 "looks" 重建了我的示例,使其成为正确的标准,但是这段代码太丑了,看起来就像是用 confogulus 棍子打过,然后浸入了一个 confutious 罐子里被可怕地油炸:

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. 这会被认为是好的代码,还是我应该使用 Enigmativity 代码中定义的 OnTestHappening 方法?
  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));
    }
}