.NET委托类型的适当命名约定是什么?

93

按照惯例,类通常以名词命名,方法通常以动词命名,接口通常以形容词命名。

委托的常见命名约定是什么?或者在将委托列在类型和其他内容中时,有什么好的区分名称的方法?

我的直觉是像形容词一样更可能给委托起名字,因为单个方法接口通常可以用委托替换。

一些想法:

delegate object ValueExtracting(object container);

delegate object ValueExtractor(object container);

delegate object ValueExtractionHandling(object container);

delegate object ValueExtractionHandler(object container);
8个回答

125

个人使用几种不同的模式:

[任务][状态]处理程序 - UITaskFinishedHandler

[事件]处理程序 - ControlLoadedHandler

[函数名]委托 - DoSomeWorkDelegate - 用于创建一个委托,在不同/新线程上调用函数时使用。

[任务]回调 - ContainerLoadedCallback - 当控件A开始一个动作,控件B完成大部分工作并且控件A已经传递了依赖项到控件B(例如,ControlA可能已经传递了一个UI容器供ControlB填充,并需要通知来实际显示容器)时使用。

当您的项目使用大量多线程或异步WCF调用时,可能会出现很多委托对象,因此采用至少对您有意义的标准非常重要。


4
"[Function Name]Delegate" 违反了 CA1711 规范。不幸的是,我喜欢根据是否有返回类型来使用 "[Function Name]Func" 或者 "[Function Name]Action"。请注意,这里没有提供额外解释。 - Tinister
1
这可能是我迄今为止看到的最有用(也是最短)的约定。我给你点赞。感谢@slugster分享。 - FullStackForger
代码规则告诉你不要在任何委托后缀中使用Delegate https://learn.microsoft.com/en-us/visualstudio/code-quality/ca1711-identifiers-should-not-have-incorrect-suffix?view=vs-2017 - Christian Findlay
1
@MelbourneDeveloper 这是一个有用的参考资料,但请注意它是针对发布于我回答之后6年的分析器/编译器/产品而发布的。此外,当您有许多委托在浮动,因为技术堆栈严重依赖于多线程,并且它不提供任何内置的编译时支持时,Delegate 后缀非常有用。 - slugster
3
@MelbourneDeveloper 告诉那些为 asp.net-core 创建了 RequestDelegate 的人们 ;-] - t3chb0t
显示剩余3条评论

58

Microsoft的框架设计指南 - 对我来说是一个命名年鉴,在这个主题上说以下内容

√ 对于用于事件的委托名称,应添加后缀“EventHandler”。
√ 对于非用作事件处理程序的委托名称,应添加后缀“Callback”。
X 不要将“Delegate”后缀添加到委托中。


24
有趣的是微软说“不要将后缀“Delegate”添加到委托”,但在此示例中,他们有一个名为ProcessBookDelegate的委托。 - PadawanLondon
2
@PadawanLondon 在asp.net-core中,RequestDelegate也有同样的故事——一致性和编码规范问题很多。我猜他们甚至没有阅读自己的文档。 - t3chb0t

19

委托(delegate)是执行某个操作的东西(动词),因此,委托的名称应该是执行该操作的对象的名称。以Converter<TInput, TOutput>为例,这里的动词是Convert,进行转换的对象被称为转换器(converter),因此委托的名称也应该是“转换器”。


6
这取决于几个因素。
如果委托将用作事件,它应该始终被称为EventHandler子类型,例如:
public delegate void ValueExtractingEventHandler(object sender,
    ValueExtractingEventArgs e);

如果不是事件,那么微软编码准则(我似乎在谷歌上找不到正确的副本)明确建议委托名称中不要包含“delegate”或“handler”等词语,除了特殊情况下的“EventHandler”类型。
通常,委托应该根据动作命名,比如在提取值之前发生的委托可以命名为“ValueExtracting”,提取值后的委托可以命名为“ValueExtracted”。
“Func<T1, T2, ..., TResult>”委托语法也越来越普遍,但是除非有4个或更多参数传入,否则您根本不需要声明自己的委托 - 只需使用现有的即可。
object ExtractObject(object source, Func<object, object> extractor);

当委托被用作闭包时,此语法最佳。 委托本身没有非常有趣的名称,但参数是一个代理名词(提取器、提供者、评估器、选择器等)。

大多数委托用法都适用于上述类别之一,因此请确定它被用于哪个类别并选择适当的方式。


3

我以前没有考虑过这件事,主要是因为我只使用EventHandler<T>Func<T>或者Action<T>中的一个重载,从来没有费心去定义自己的。如果我必须选择一个,我可能会选择ValueExtractor。这使得它听起来更像一个对象,当你调用它时,你将使用该对象执行一个操作。例如:

ValueExtractor extractor += Blah;
var value = extractor(data);

此外,大多数内置委托也是以名词命名的。如果不确定,请遵循.NET框架。

1
基于 Enumerable.Sum,我会将委托作为 Func<object, object> 传递,并将参数命名为 selector
void Foo(Func<object, object> selector) ...

如果你必须为此创建自己的委托,我会选择 ValueExtractor,因为这是最能描述它所做的事情的名称。

2
这些通用的委托(Action和Func)在95%的情况下都很好用。但是,在委托具有复杂签名并且被频繁传递时,它们有时会非常不足。基本上,每个参数的作用应该是显而易见的,如果不是,建议创建一个命名的委托。 - Matěj Zábský

0

我会选择ValueExtraction。
我从来没有想过为什么,但我猜可能是因为你在存储一个操作,而它应该是一个名词。 严格来说,这不是一个操作,我知道...


0
在事件(使用委托)的情况下,Windows Forms 使用以下约定:
委托:
public delegate void MouseEventHandler(object sender, MouseEventArgs e);

事件:

public event MouseEventHandler MouseClick;

事件监听器:

this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseClick);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接