枚举命名规范 - 复数形式

357

我阅读过类似但不是完全符合我的需求的问题,现在还想提出一个问题,这个问题可以在 C# naming convention for enum and matching property 找到。

我发现我有一个倾向,那就是将枚举命名为复数形式,然后作为单数使用,例如:

public enum EntityTypes {
  Type1, Type2
}

public class SomeClass {
  /*
    some codes
  */

  public EntityTypes EntityType {get; set;}

}

当然这个方法可以工作,而且这是我的风格,但是有没有人能够找出这种约定的潜在问题?我使用了一个带有 "Status" 一词的 "丑陋" 命名:

public enum OrderStatuses {
  Pending, Fulfilled, Error, Blah, Blah
}

public class SomeClass {
  /*
    some codes
  */

  public OrderStatuses OrderStatus {get; set;}

}

附加信息: 也许我的问题没有表述清楚。当我定义枚举类型的变量时,经常需要费尽心思去命名它们。我知道最佳实践是什么,但这并不能帮助我轻松地命名那些变量。

我不可能把所有的枚举属性(比如“状态”)都暴露为“MyStatus”。

我的问题是:有人能找出上述约定潜在的问题吗?这不是关于最佳实践的问题。

问题重述:

好吧,我想我应该这样问:有没有一种好的通用方法来命名枚举类型,以便在使用时,枚举“实例”的命名将会非常直观明了?


6
公共枚举类型OrderState... - 公共属性OrderStatus { get; set;} - Fraser
根据其他评论和答案,我们最好不要在枚举名称中使用复数形式。这几乎必然会导致在给相应字段命名时出现问题,我对此没有解决办法。我会在数组和集合中使用复数形式,在这种情况下,我会忽略常见的英语语法,只是添加一个's'。因此,表示状态的元素的集合将被称为"statuss"。;-) - Giorgio Barchiesi
一般来说,系统匈牙利命名法不被提倡。这是一个关于在枚举名称前缀/后缀中加入某些数据类型标识符的通用评论,这种做法通常是不好的实践,应该避免使用。 - Erik Philips
10个回答

433

微软建议在使用Enum表示位字段时使用复数形式(同时使用FlagsAttribute)。查看枚举类型命名约定(Microsoft的命名指南的子集)。

关于您的澄清,我认为以下两种说法都没有问题:

public enum OrderStatus { Pending, Fulfilled, Error };

public class SomeClass { 
    public OrderStatus OrderStatus { get; set; }
}

或者

public enum OrderStatus { Pending, Fulfilled, Error };

public class SomeClass {
    public OrderStatus Status { get; set; }
}

28
是的,这是一个正确的答案。这些指南在 .Net Framework 中被使用,例如枚举类型 DayOfWeek 和标志枚举类型 RegexOptions。 - Alexander Zwitbaum
3
是的,这是推荐做法,我欢迎它。然而,它并没有回答我的问题。 - o.k.w
1
@o.k.w 进一步阐述,虽然看起来不太美观,但如果您需要从标志枚举中获取单个值,请使用字段/属性/参数的单数形式。如果支持设置多个标志,则使用复数形式。如果您的枚举不是标志枚举,请在类型名称和字段/属性/参数中使用单数形式。 - Jonathan Dickinson
4
这是答案中链接到微软命名约定指南的.NET 4.0版本的链接。 - user456814
2
@Thomas 我从未遇到过问题,我不明白为什么它不能工作--我看不出会有歧义是引用类型还是变量的上下文。例如 OrderStatus == OrderStatus.Pending 被识别为左侧的变量,右侧则是枚举。 - James Hurley
显示剩余2条评论

49

我最开始将枚举类型命名为复数形式,但后来改成了单数形式。在使用上下文中,单数形式更加合理。

enum Status { Unknown = 0, Incomplete, Ready }

Status myStatus = Status.Ready;

与之比较:

Statuses myStatus = Statuses.Ready;

在这种情况下,我认为单数形式听起来更自然。我们达成了一致:当声明枚举时(这只发生在一个地方),我们会想到“这是一组某些东西”,但在使用它时,可能会发生多次,我们会想到“这是一种某些东西”。


8
有点晚的反应(也许有点跑题),但我的建议是:建议将值“0”用于未知值,这样未初始化的变量默认为“未知”。 - SvenL
1
同意,@SvenL。已相应更新示例。 - Bob Kaufman

32

这种情况从来不适用于复数形式。

enum 显示了某个事物或属性的特征。我来举个例子:

enum Humour
{
  Irony,
  Sarcasm,
  Slapstick,
  Nothing
}

你可以只有一种类型,但尝试将其视为多个类型,而不是复数:

Humour.Irony | Humour.Sarcasm

而不是

Humours { Irony, Sarcasm }

你有幽默感,你没有幽默感(humours)。


12
哈哈,好的,程序员并不总是语法/政治正确。在你的情况下,我可能会使用“HumourTypes”。可能是个坏习惯吧。 - o.k.w
1
如果我想搜索所有具有讽刺感或者幽默感的个体,那么我不是应该将一个包含 Humours.Irony | Humours.SarcasmHumours 实例传递给搜索程序吗? - Charles Bretana

18

这是我与常规意见不合的少数几个地方之一。说实话,我讨厌定义枚举和枚举实例可以使用相同名称这一点。我会将所有的枚举结尾都加上 "Enum",特别是因为它使得在任何给定的用法中,上下文更加清晰明了,我认为这使得代码更易读。

public enum PersonTypesEnum {
    smart,
    sad,
    funny,
    angry
}


public class Person {   
    public PersonTypesEnum PersonType {get; set;}
}

没有人会混淆枚举和它的实例。


4
我来这里寻找枚举命名规范,因为我有一个与类和枚举同名的情况,并希望有“某种方法”使其更加明显。我想在枚举名称前面加上“E”(代表枚举),就像我们在接口名称前面加上“I”一样。但是,我喜欢你的解决方案,Heather!好棒!!! - Scott
8
根据微软的设计指南:“在枚举类型名称中不要使用“Enum”后缀。” - Thoryn Hawley
12
也许你错过了我说的第一句话?让我复制并粘贴给你看:“这是我在少数几个地方不同意惯例并且会反对它的地方之一。” 然后我继续解释原因。 - Heather
1
我理解你在各种可能的方式上都违反了指南。但这只是为人们树立了不好的榜样,特别是在程序中如何命名任何东西方面。我们不应该用后缀列表来命名列表,而是应该使用适当的名称来表示实际代表的实体。包括枚举在内的所有内容都应根据其所代表的实体进行命名。 - Rohin Tak
9
我并非“以任何可能的方式”违反指南。那是夸张的说法。我只是在某个具体的方面违反了指南,但这种做法是有道理支持的。如果你不同意,可以列出你不同意的理由;你的夸张言辞是不必要的,也无助于你的立场。 - Heather
6
如果可能存在命名空间冲突,我认为添加Enum没有问题。作者并没有建议在所有变量后面都加上它们的类型后缀,因此这并不是一个问题。另外,作者提供了理由,这使得他的论点更有说服力,而微软公司则没有提供任何理由。 - Jai Govindani

17

通常来说,最佳实践建议是使用单数形式,除非那些附有[Flags]属性的枚举(因此可以包含位字段),这些应该使用复数形式。

阅读您编辑后的问题后,我感觉您可能认为属性名称或变量名称必须与枚举类型名称不同...其实不需要。以下是完全可以接受的...

  public enum Status { New, Edited, Approved, Cancelled, Closed }

  public class Order
  {
      private Status stat;
      public Status Status
      { 
         get { return stat; }
         set { stat = value; }
      }
  }

是的,我想我的方法是一种“快速而懒惰”的方式,可以避免在使用枚举时需要考虑名称的问题。 - o.k.w
1
支持你的回答:在 MSDN 上,从类型成员名称中的“属性名称”部分:✓ 考虑给属性与其类型相同的名称。 例如: public Color Color { get {...} set {...} } - DavidRR

9

如果您试图编写像这样简单而被禁止的代码:

    public class Person
    {
        public enum Gender
        {
            Male,
            Female
        }
        //Won't compile: auto-property has same name as enum
        public Gender Gender { get; set; }  
    }

您的选择是:
  1. Ignore the MS recommendation and use a prefix or suffix on the enum name:

    public class Person
    {
        public enum GenderEnum
        {
            Male,
            Female
        }
        public GenderEnum Gender { get; set; }
    }
    
  2. Move the enum definition outside the class, preferably into another class. Here is an easy solution to the above:

    public class Characteristics
    {
        public enum Gender
        {
            Male,
            Female
        }
    }
    public class Person
    {
        public Characteristics.Gender Gender { get; set; }  
    }
    

2
假设的情况,不是一个好的解决方案。为什么一开始要使用嵌套的enum,然后再将其嵌套到另一个类中,如果这会引起麻烦呢? - Gert Arnold
1
在性别方面,将属性名称设置为“Gender”,枚举名称设置为“Sex”更有意义。所以,“isac.Gender = Sex.Male”。 - nawfal
5
我不确定为什么这个人被投票踩了。这种情况是真实存在的,而非假设的。在C#中嵌套枚举类型的原因与在Java中使用内部类相似,因为内部类型仅在外部使用,不会在其他地方使用,并且只有在外部上下文中才有意义。由于编译器的限制,你必须选择提到的解决方案之一。 - asdfjklqwer
你需要从某个地方设置它,通常是在类外部,或者可能在构造类时,在这种情况下,除非你想发送Person.Gender.Male,否则需要在外部定义枚举,Gender可能适用于更多的东西,我认为不将其嵌套是最好的解决方案。 - Jim Wolff
2
另一个可能更好的选择是"Serge - appTranslator"的答案。 - Curtis Yallop

7
稍有些晚了...
你的问题和你提到的那个问题(我问过的)之间有一个重要的区别:
你将枚举定义放在类外部,这使得枚举和属性可以使用相同的名称:
public enum EntityType { 
  Type1, Type2 
} 

public class SomeClass { 
  public EntityType EntityType {get; set;} // This is legal

}

在这种情况下,我会遵循微软的指南并为枚举使用单数名称(对于标志使用复数)。这可能是最简单的解决方案。
我的问题(在其他问题中)是当枚举在类的范围内定义时,会阻止使用与枚举完全相同命名的属性。

7

最佳实践-使用单数。您有一个由枚举项组成的列表。当您说“Versions.1_0”时,从列表中使用一个项听起来很奇怪。更合理的做法是说“Version.1_0”,因为只有一个1_0版本。


1
使用复数形式来声明枚举的原因是在声明时我们会声明多个值,所以复数看起来很好... 但是我们忽略了一个事实,即当声明枚举时,它指定了它可以具有的值(从给定的值集合中)。这并不意味着该枚举的实例将存储多个值..... 当我们写下: enum Days { MON, TUE, WED, THU, FRI, SAT, SUN }; 我们之所以使用复数是因为提供了多个值.. 然而,在使用时(Days day = Days.MON;),我们完全忽略了该枚举的实例应该具有单个值的事实.... 因此,当我们写下: enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }; 我们的意思是有一个枚举可以拥有任何一天作为它的值,所以单数更合适。 虽然(如上所述),避免使用单数名称的方法是使用任何类型的指示器,例如DayEnum或EDay(我更喜欢第二种)....

0
在另一个线程C# 枚举和匹配属性的命名约定中,有人指出了我认为是一个非常好的想法:
“我知道我的建议违反了.NET命名约定,但我个人会用'E'作为枚举的前缀,用'F'作为枚举标志的前缀(类似于我们将接口用'I'作为前缀)。”

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