根据Microsoft事件命名准则,senderC#事件处理程序中的参数" 始终是类型对象,即使可以使用更具体的类型".
这导致了许多事件处理代码,如:
RepeaterItem item = sender as RepeaterItem;
if (item != null) { /* Do some stuff */ }
Run Code Online (Sandbox Code Playgroud)
为什么约定建议不要使用更具体的类型声明事件处理程序?
MyType
{
public event MyEventHander MyEvent;
}
...
delegate void MyEventHander(MyType sender, MyEventArgs e);
Run Code Online (Sandbox Code Playgroud)
我错过了一个陷阱吗?
对于后人:我同意的答案一般情绪的惯例是使用对象(并通过传递数据EventArgs),即使它是可以使用更具体的类型,而在现实世界编程它是按照重要大会.
Jon*_*eet 39
嗯,这是一种模式而不是规则.它确实意味着一个组件可以从另一个组件转发事件,保留原始发件人,即使它不是引发事件的正常类型.
我同意这有点奇怪 - 但为了熟悉起见,它可能值得坚持惯例.(熟悉其他开发人员,就是这样.)我从来没有特别热衷于EventArgs自己(因为它本身并没有传达任何信息)但这是另一个话题.(至少我们EventHandler<TEventArgs>现在已经有了- 虽然如果EventArgs<TContent>你只需要传播一个值的常见情况也会有所帮助.)
编辑:它确实使委托更具通用性 - 单个委托类型可以在多个事件中重用.我不确定我是否认为这是一个特别好的理由 - 特别是考虑到仿制药 - 但我想这是 ......
Kei*_*ith 17
我认为这个会议有充分的理由.
让我们来看看(并展开)@ erikkallen的例子:
void SomethingChanged(object sender, EventArgs e) {
EnableControls();
}
...
MyRadioButton.Click += SomethingChanged;
MyCheckbox.Click += SomethingChanged;
MyDropDown.SelectionChanged += SomethingChanged;
...
Run Code Online (Sandbox Code Playgroud)
这是可能的(并且自从.Net 1以来,在泛型之前)因为支持协方差.
如果您是自上而下的话,那么您的问题就很有意义 - 即您需要在代码中使用该事件,因此您将其添加到您的控件中.
但是,惯例是在首先编写组件时更容易.您知道,对于任何事件,基本模式(对象发送者,EventArgs e)都可以工作.
当您添加事件时,您不知道它将如何使用,并且您不希望任意约束使用您的组件的开发人员.
您的通用强类型事件示例在您的代码中很有意义,但不适合其他开发人员编写的其他组件.例如,如果他们想要将您的组件与上述组件一起使用:
//this won't work
GallowayClass.Changed += SomethingChanged;
Run Code Online (Sandbox Code Playgroud)
在此示例中,附加的类型约束只会给远程开发人员带来痛苦.他们现在必须为您的组件创建一个新的委托.如果他们正在使用您的组件的负载,他们可能需要每个组件的委托.
我认为这个约定值得关注任何外部的,或者你希望在一个紧密的团队之外使用.
我喜欢通用事件args的想法 - 我已经使用了类似的东西.
Chr*_*uts 10
当我更喜欢强类型的发件人时,我使用以下代理.
/// <summary>
/// Delegate used to handle events with a strongly-typed sender.
/// </summary>
/// <typeparam name="TSender">The type of the sender.</typeparam>
/// <typeparam name="TArgs">The type of the event arguments.</typeparam>
/// <param name="sender">The control where the event originated.</param>
/// <param name="e">Any event arguments.</param>
public delegate void EventHandler<TSender, TArgs>(TSender sender, TArgs e) where TArgs : EventArgs;
Run Code Online (Sandbox Code Playgroud)
这可以通过以下方式使用:
public event EventHandler<TypeOfSender, TypeOfEventArguments> CustomEvent;
Run Code Online (Sandbox Code Playgroud)
泛型和历史将发挥重要作用,尤其是暴露类似事件的控件(等)的数量.没有泛型,你最终会暴露很多事件Control,这在很大程度上是无用的:
object)如果我们考虑泛型,那么一切都很好,但是你开始涉及继承问题; 如果类B : A,则应该在事件A是EventHandler<A, ...>,和事件B是EventHandler<B, ...>?同样,非常令人困惑,难以使用工具,并且在语言方面有点混乱.
直到有更好的选择涵盖所有这些,object工作; 事件几乎总是在类实例上,所以没有拳击等 - 只是一个演员.而且铸造不是很慢.
| 归档时间: |
|
| 查看次数: |
16166 次 |
| 最近记录: |