C#中泛型的良好命名约定是什么?[关闭]


16

我决定在这里问这个问题,而不是在堆栈溢出时问这个问题,因为它相当主观。

在C#中,通常我会看到名称很差的泛型类型。具体来说,“ T”是常用的,但其本身并不是有意义的名称。例如:

class Fruit<T>
{
    T fruit;
}

虽然这是典型的方法,但有人会反对吗?如果是这样,那么在C#泛型函数和类的上下文中,泛型的合理命名约定是什么?

在我之前的示例中,让我们假设泛型类型T必须始终是水果的类型,例如AppleOrange。该类型T需要使它很明显地表明它是水果的类型,所以也许更好的名称是FruitType,所以我们最终得到:

class Fruit<FruitType>
{
    FruitType fruit;
}

这只是为了给大家我正在寻找的想法。这个问题可以接受的“经验法则”是什么?


3
这不是一个建设性的问题。它只会获得海报最喜欢的样式的答案。
Michael

1
看一下约束,考虑您的示例:msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Matthieu

2
@Michael会有很多答案,被接受的答案将是Robert的最爱,但其他各种答案也会被投票通过。
StuperUser 2011年

5
@Michael主观问题得到主观答案。这个问题仍然具有建设性,因为它可以作为任何想要针对此特定问题提出各种想法/解决方案的人的参考点。我标记为答案的那一个并不能代表一个唯一的有用信息。
void.pointer 2011年

也许将其转变为社区Wiki,作为一种很好的(虽然主观的)资源?
tylermac

Answers:


22

这的确是主观... 十岁上下
正如某些人发现i对于for循环变量T完全有效,有些人认为对泛型类中的类型占位符完全有效。

我个人拥护这种方法,这是一种常见的约定,人们通常都知道您的意思。

在类型有意义的地方,我会使用有意义的名称,但通常以T开头。我最近开发了一个通用的字典类(不要问),声明是

public class Dictionary<TKey, TValue>

但是,对于像元组这样的类型基本上没有意义的东西,我认为以下内容完全可以接受。

public class Tuple<T1, T2, T3>

2
我根本不觉得这是主观的。iT工作,这在原则上是可以衡量的(即,如果循环索引获得不同的标识符,则可以提高对源代码的理解程度)。仅仅因为难以衡量并不意味着我们必须在所有内容上加上“主观”标签。考虑到没有明显问题的广泛使用,即使不衡量这实际上是有效的,也可以说是相当合理的。
Konrad Rudolph

2
@康拉德:你有一点。。。但是问题并没有被标记为主观的,询问者承认这是一个主观的主题,假设人们倾向于对命名约定有自己的偏好。因此,尽管该问题可能不是主观的(事实上,它不是正确答案,即链接到Microsoft官方指南的答案),但该主题是主观的,因为我敢肯定有人会发布“ i并且T邪恶的。永远不能使用单个字母名称”类型答案。增加了一个ISH来帮助大家satisify :)
二进制杞人忧天

1
我认为仅此评论中添加的评论使其成为非常有价值的回复,尽管答案本身非常有帮助。T当我们谈论没有约束的类型时,这TFruit是有道理的,因为它对我说:“任何有约束的类型都是水果”。命名通用类型参数似乎是一个很好的“经验法则”。谢谢!!
void.pointer

1
请注意,这与MSDN中针对库开发人员.NET Framework设计指南相一致。请参阅:通用类型参数的名称
Grant Thomas

7

我认为您是对的,尽管T已成为相当标准。它可能起源于旧的C ++时代和“ T型”字样。我认为这是一种很好的做法,尽可能多地描述,但这是主观的。

您可以选择T作为前缀,就像许多人选择I作为接口一样。从而

class Juice<TFruit> where TFruit...

以我的拙见,这将是一个好名字。在大多数情况下,我更喜欢使用前缀作为后缀,因为当您偶然发现时会立即看到您所看到的内容,并且使用Intellisense之类的内容更容易搜索。同样,对于UI控件来说也是一种好习惯,当您很可能总是知道类型(例如TextBox),但不确定100%确定给它指定的名称时。

不利的一面是,当类型本身以T开头时,它看起来很糟糕。因此,我认为在特殊情况下为通用类型添加后缀是一件好事,例如以下示例。

class SomeAlgorithm<TypeT> where TypeT : Type

请注意,这仅是我的看法,并且具有很高的主观性。但是我确实认为我有一个小问题,就是喜欢使用前缀而不是后缀。


在框架设计准则中明确要求T为类型参数和I接口名称使用前缀(“ DO ...”规则)。
理查德

1
令人怀疑的是,TFruit这里使用的是什么T。使用诸如TType或的名称TypeT肯定是胡说八道。它仅在上添加任何信息T。传达的信息完全相同。
康拉德·鲁道夫

@Konrad Rudolph:仔细看看我的TypeT示例,它涉及到处理System.Type的特殊情况。我确实认为我的名字具有比使用T更高的熵,尤其是在泛型也受约束的情况下。
猎鹰

7

Microsoft有一个有关泛型的正式指南:类,结构和接口的名称在此引用,并以书的形式:Framework Design Guidelines)。

关于您的特定问题,它说:

请勿使用描述性名称来命名泛型类型参数,除非单个字母的名称完全可以自我解释,并且描述性名称不会增加价值。

IDictionary<TKey, TValue> 

是遵循此准则的界面示例。

对于具有一个单字母类型参数的类型,考虑使用字母T作为类型参数名称。

在描述性类型参数名称前加上字母T。

考虑以参数名称指示对类型参数施加的约束。例如,约束到ISession的参数可以称为TSession。


更好的参考书是《框架设计指南》书或有关MSDN的(摘要),尤其是类名称,结构名称和接口名称
理查德

@Richard:考虑到您的评论,调整了我的答案,谢谢!
Matthieu

2

泛型的全部要点是委托功能-泛型类做一件事,其参数做另一件事。教科书示例是一个通用集合:该集合存储“事物”,但并不关心这些事物是什么。因此,泛型名称(sic!)具有一定的逻辑性-我们不希望它具有描述性,因为除了“它是泛型类型参数”之外,没有其他可描述的名称,泛型名称T包含了该名称。惯例)。描述性是好的,但是描述性过强则意味着没有限制。

但是,有时,泛型类或方法具有多个类型参数,在这一点上,给它们更多描述性的名称是有意义的,这样它们的作用就变得显而易见。一个很好的例子是键值集合类型,其中键和值都是通用的。称他们TS(或Q任何东西)将比调用它们(例如KeyTypeValueType,或或TKey和)有用TVal


1

答案确实是主观的。但是,它确实有一个问题,因为代码应该自我记录,我们可能都可以学到一些更好的方法来做到这一点。

以下是我学习并遵循的约定:

  • 泛型类型参数永远不应被误认为是具体类。通常,这会鼓励您为自己写序,T无论后面如何做,都非常像接口通常以开头I

  • 通常应该在类或方法上标记单个泛型类型参数T。这是可以理解的通用约定,可以追溯到C ++模板。

  • 同一类或方法声明上的多个泛型类型参数都应以T开头,但应通过一些简洁但可理解的方式加以区分。TIn并且TOut,例如,是用于接受一个强类型的通用输入,并产生一个强类型通用输出的方法常见和公知的绿茶多酚。

  • 可以将多个区分但不明显的类型(例如,.Net的Tuple等包含类或Func,Predicate和Action的委托类型)标记为T1,T2,T3等。但是,“显着”的GTP声明(具有明确的目的和/或非常具体的类型限制)应具有更多描述性。

  • 与包含类的泛型类型不同的方法上的单个泛型类型可以遵循先前关于类或方法中的多个类型的规则,或者如果该类型除其他以外没有什么不同,则可以赋予不同的类型单个字母,通常是UV。这又是可以追溯到C ++模板的约定。

  • 无论您选择做什么,都要保持一致;请勿为一个类别标记GTP T,而为下一个类别标记GTP TParam,除非第二个类别嵌套在第一个类别中,而第二个类别则T无法使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.