上一篇文章:
Event Signature in .NET — Using a Strong Typed 'Sender'?
In a C# event handler, why must the “sender” parameter be an object?
Microsoft的约定和指南强制.NET用户使用特殊模式在.NET中创建,引发和处理事件。
活动设计指南http://msdn.microsoft.com/en-us/library/ms229011.aspx说明
引用:
事件处理程序签名遵循以下约定:
返回类型为Void。
第一个参数名为sender 并且是Object类型。这是 引发事件的对象。
第二个参数名为e和 是EventArgs类型或派生类型 EventArgs的类。这是 事件特定数据。
该方法只需两个 参数。
这些约定告诉开发人员(以下)更短更明显的代码是邪恶的:
public delegate void ConnectionEventHandler(Server sender, Connection connection);
public partial class Server
{
protected virtual void OnClientConnected(Connection connection)
{
if (ClientConnected != null) ClientConnected(this, connection);
}
public event ConnectionEventHandler ClientConnected;
}
和(以下)更长和更不明显的代码是好的:
public delegate void ConnectionEventHandler(object sender, ConnectionEventArgs e);
public class ConnectionEventArgs : EventArgs
{
public Connection Connection { get; private set; }
public ConnectionEventArgs(Connection connection)
{
this.Connection = connection;
}
}
public partial class Server
{
protected virtual void OnClientConnected(Connection connection)
{
if (ClientConnected != null) ClientConnected(this, new ConnectionEventArgs(connection));
}
public event ConnectionEventHandler ClientConnected;
}
虽然这些指导原则没有说明为什么遵循这些惯例如此重要,让开发人员像猴子一样不知道为什么以及他们在做什么。
恕我直言,微软的.NET事件签名约定对你的代码不利,因为它们会在编码,编码和编码上花费额外的零效率工作:
这并不难做到这一点,但实际上讲的是当我们不遵守微软的惯例时我们会失去什么,除非人们把你当作异教徒,因为你的行为与微软的惯例verges on blasphemy对抗:)< / p>
你同意吗?
答案 0 :(得分:3)
关于拥有强类型的发件人,我经常想知道自己。
关于EventArgs,我仍然建议您使用中间的EventArgs类,因为您可能希望将来添加您目前无法预见的事件信息。如果您一直使用特定的EventArgs类,则可以简单地更改类本身以及触发它的代码。如果按照示例传递Connection,则必须重构每个事件处理程序。
修改强>
Jim Mischel在评论中提出了一个很好的观点。通过使发件人成为object
,我们可以启用相同的事件方法,以便可以重复使用它来处理各种事件。例如,假设网格需要在以下情况下自行更新:
然后你可以说出这样的话:
serverBus.EntryReceived += RefreshNeededHandler;
refreshButton.Click += RefreshNeededHandler;
...
public void RefreshNeededHandler(object sender, EventArgs args)
{
...
}
当然,在实践中,我几乎没有任何关于这种重用的调用,而在很多情况下,我倾向于使用的第一件事是将sender
强制转换为我的对象类型知道它必须是。如果我想重用这样的处理程序,我认为将两个处理程序都调用相同的方便方法就足够了。对我来说,事件处理程序在概念上应该处理特定对象组上的特定类型的事件。所以我个人并不相信object sender
方法是最好的惯例。
但是,我可以想象这会非常方便的情况,比如你想记录每个被触发的事件。
答案 1 :(得分:3)
您将遇到的问题:
当你添加另一个参数时,你 将不得不改变你的活动 处理程序签名
当程序员第一次看时 您的代码,您的事件处理程序将 看起来不像事件处理程序。
尤其是后者可能比写5行课更浪费你的时间。
答案 2 :(得分:2)
我在不遵循惯例时看到的最大问题是,您将混淆习惯于以运行时库的方式处理事件的开发人员。我不会说约会好或坏,但肯定不是邪恶。 .NET开发人员了解并了解如何使用符合Microsoft指南编写的事件。在此基础上创建自己的事件处理机制可能在运行时更有效,甚至可能导致您认为更清晰的代码。但它会有所不同,你最终会在你的程序中处理两个事件处理“标准”。
我的立场是,使用一个不太理想的标准(只要它不会被严重破坏)比使用两个相互竞争的标准更好。
答案 3 :(得分:1)
我使用强类型事件(而不是对象,因为它节省了我必须进行投射),它真的不难理解,“哦,看起来他们使用的是不是对象的类型”
对于eventArgs,你应该使用它来防止对象根据@StriplingWarrior回答而改变。
我不明白为什么开发者会对此感到困惑?