【发布时间】:2015-06-01 09:55: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 );
对于我访问的其他链接,我只能找到与我的代码(在委托、处理程序或属性中)的 1 个相似之处,但找不到与我的代码相关的任何内容以实际灌输那个“尤里卡”时刻
编辑 2:我现在已经用“看起来”作为正确标准重新构建了我的示例,但是这段代码非常丑陋,看起来就像是用 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;
}
}
- 这会被认为是好的代码,还是应该使用 Enigmativity 代码中定义的
OnTestHappening方法? - 为什么我不能使用无参数委托?它现在使用默认的
( object sender, EventArgs e ),但这感觉有点矫枉过正,而且编译器对此感到满意并没有道理,但根据编码标准,它被认为是糟糕的代码?我不是在争论标准,而是试图理解它的推理。
【问题讨论】:
-
你读过msdn.microsoft.com/en-us/library/ms182133.aspx 吗?特别是,看看你的代表的签名......
-
您正在注册一个指向当前执行方法的事件处理程序。那是对的吗?你不是说把方法
Go注册为eventhandler吗? -
嗯,这不是线程安全的,首先...您为什么不只订阅一次呢?基本上你有一个非常奇怪的情况,你在问题中根本没有提到......这与你遇到的问题并不真正相关,那就是你违反了事件约定然后表现得很惊讶一个约定检查代码分析工具在向你抱怨。
-
如果你觉得你没有理由传递sender和一个空的
EventArgs对象,那么不要,没关系。显然,一个旨在警告您违反 MS 编码标准的工具会在您不遵循这些标准时向您发出警告。只要您知道您没有遵循标准并且觉得您的代码在不遵循标准时更好,那么这就是您的选择。就其本质而言,风格选择是主观的。 -
@Storm:答案是“第一个是事件约定,第二个不是”。见msdn.microsoft.com/en-us/library/vstudio/ms229011。这只是一个约定 - 如果您违反它,您的代码仍然可以工作......
标签: c# events callback delegates