【问题标题】:C# naming convention for enum and matching property枚举和匹配属性的 C# 命名约定
【发布时间】:2009-01-30 10:24:28
【问题描述】:

我经常发现自己实现了一个类,它维护某种自己的状态属性作为枚举:我有一个 Status 枚举和一个 Status 类型的 Status 属性。我应该如何解决这个名称冲突?

public class Car
{
  public enum Status
  {
    Off,
    Starting,
    Moving
  };

  Status status = Status.Off;

  public Status Status // <===== Won't compile =====
  {
    get { return status; }
    set { status = value; DoSomething(); }
  }
}

如果 Status 枚举对不同类型是通用的,我会把它放在类之外,问题就会得到解决。但 Status 仅适用于 Car,因此在类之外声明枚举是没有意义的。

在这种情况下您使用什么命名约定?

注意:这个问题在this question 的答案中得到了部分讨论。由于它不是主要问题,因此没有引起太多关注。

编辑:Filip Ekberg 针对“状态”的特定情况提出了 IMO 极好的解决方法。然而,我会很高兴阅读有关枚举/属性名称不同的解决方案,如 Michael Prewecki 的答案

EDIT2(2010 年 5 月):我最喜欢的解决方案是将枚举类型名称复数,正如 Chris S 所建议的那样。根据 MS 指南,这应该仅用于标志枚举。但我越来越喜欢它了。我现在也将它用于常规枚举。

【问题讨论】:

  • 如果你想让枚举嵌套在你的类中,我认为没有很多好的解决方案。我实际上更喜欢将枚举分开然后它不会出现问题,但我可以从哲学上看到你想要嵌套它的观点。

标签: c# .net enums naming-conventions


【解决方案1】:

“关闭”、“开始”和“移动”的定义就是我所说的“状态”。当您暗示您正在使用“状态”时,它就是您的“状态”。所以!

public class Car
{
  public enum State
  {
    Off,
    Starting,
    Moving
  };

  State state = State.Off;

  public State Status
  {
    get { return state ; }
    set { state= value; DoSomething(); }
  }
}

如果我们再举一个例子,你想在这种情况下使用“类型”这个词:

public class DataReader
{
    public enum Type
    {
        Sql,
        Oracle,
        OleDb
    }

    public Type Type { get; set; } // <===== Won't compile =====

}

你真的需要看看枚举和枚举之间是有区别的,对吧?但是在创建框架或谈论架构时,您需要关注相似之处,好吧,让我们找到它们:

当某物被设置为状态时,它被定义为“事物”状态

示例:汽车的状态为运行状态、停止状态等。

你想在第二个例子中实现的有点像这样:

myDataReader.Type = DataReader.Database.OleDb

您可能认为这与我一直在向其他人宣传的内容相反,您需要遵循一个标准。但是,您遵循的是标准! Sql-case 也是一个特定的案例,因此需要一个特定的解决方案。

但是,枚举可以在您的 System.Data 空间中重复使用,这就是模式的全部意义所在。

“类型”的另一种情况是“动物”,其中类型定义了物种。

public class Animal
    {
        public enum Type
        {
            Mammal,
            Reptile,
            JonSkeet
        }

        public Type Species{ get; set; }

    }

这是遵循一种模式,您不需要为此“了解”对象,并且您没有指定“AnimalType”或“DataReaderType”,您可以在您选择的命名空间中重复使用枚举。

【讨论】:

  • 我相信“状态”名称只是一个例子。当你不能依赖状态/状态时,其他情况呢?例如。一个类型枚举...
  • @Filip:Animal Type 样本准确地指出了我在第一条评论中的意思,即这几乎是枚举的“改写”。我认为使用枚举和属性名称的同义词会使代码有些混乱。
  • 我也认为“物种”只是类型的改写(在这种情况下是动物)。
  • 简单地重命名并不总是那么干净 - 例如考虑一个扑克牌类,具有枚举 Suit 和属性 Suit - 重命名到底是什么?无论哪种方式都很笨拙。
  • 这种做法会导致误解和混淆代码
【解决方案2】:

我会在讨论中添加我的 1 欧元,但它可能不会添加任何新内容。

显而易见的解决方案是将 Status 移出嵌套枚举。大多数 .NET 枚举(可能在 Windows.Forms 命名空间中的一些枚举除外)都没有嵌套,这使得使用 API 的开发人员很烦人,必须为类名添加前缀。

没有提到的一件事是,根据 MSDN 指南,标志枚举应该 be pluralized nouns 你可能已经知道(状态是一个简单的枚举,所以应该使用单数名词)。

State(枚举称为States)是呼格,“Status”是名词的主格,英语喜欢我们的大多数语言从拉丁语中吸收。呼格是您根据其条件命名的名词,主格是动词的主语。

换句话说,当汽车在移动时,这就是动词——移动就是它的状态。但是汽车不会熄火,它的引擎会。它也不会启动,但引擎会启动(您可能在这里选择了一个示例,因此这可能无关紧要)。

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

  public VehicleState VehicleState 
  {
    get { return _vehicleState; }
    set { _vehicleState = value; DoSomething(); }
  }
}

public enum VehicleState
{
    Stationary, Idle, Moving
}

State 是一个广义名词,描述它所指的状态不是更好吗?就像我上面做的那样

在我看来,类型示例也不是指阅读器类型,而是它的数据库。如果您描述的阅读器数据库产品不一定与阅读器的类型相关(例如阅读器的类型可能是仅转发、缓存等),我会更喜欢它。所以

reader.Database = Databases.Oracle;

实际上这永远不会发生,因为它们是作为驱动程序和继承链而不是使用枚举实现的,这就是为什么上面的行看起来不自然。

【讨论】:

  • 我的理解是flags应该是复数的,而不是简单的枚举。
  • 关于将枚举移出类,我还没有理解为什么 CarState 比 Car.State 更方便。但是,当这个枚举只描述这个类的行为时,我不理解从一个类中获取一个枚举的积极方面。
  • 我应该写像 FileOptions 这样的名词短语而不仅仅是名词,我已经更新了答案。我想 classname.Enum 只是一个偏好 - 我在框架中找不到任何我最终复制的示例。
  • 尽管 MS 说应该为标志保留复数,但随着时间的推移,我越来越喜欢这种解决方案。我现在也将它用于枚举。因此我改变了主意,接受了你的回答,而不是菲利普的。
  • 我知道我在这里晚了 1 1/2 年,但在示例中 public class EngineState 应该是 public enum EngineState,对吧?
【解决方案3】:

我认为这里真正的问题是枚举状态被封装在你的类中,这样Car.Status 对属性Status 和枚举Status 都是模棱两可的

更好的是,把你的枚举放在课堂之外:

public enum Status
{
    Off,
    Starting,
    Moving
}

public class Car
{
    public Status Status
    { ... }
}

更新

由于下面的cmets,我将在上面解释我的设计。

我是一个不相信枚举或类或任何其他对象应该驻留在内部另一个类的人,除非它在该类中是完全私有的。以上面的例子为例:

public class Car
{
    public enum Status
    {...}
    ...
    public Status CarStatus { get; set;}
}

虽然一些评论者认为 Status 在 Car 类的范围之外没有任何意义,但您设置 public 属性的事实意味着程序的其他部分使用该枚举:

public Car myCar = new Car();
myCar.CarStatus = Car.Status.Off;

对我来说是一种代码味道。如果我要查看Caroutside 状态,我不妨也将其定义为outside

因此,我可能会将其重命名为:

public enum CarStatus
{...}

public class Car
{
    ...
    public CarStatus Status { get; set; }
}

但是,如果该枚举将在 并且仅在 car 类中使用,那么我可以在那里声明该枚举。

【讨论】:

  • 这将使 Status 全局化,您可能希望将它放在特定区域内。其他类型(例如“人类”)的“状态”可能没有“开始”。但是你应该遵循一个模式。
  • 不,他很准。在 99% 的情况下,枚举与您要用于属性的单词相同。枚举只是一个命名标志,因此它对生活在外面几乎没有伤害(与包含逻辑的类不同)
  • 乔恩,这正是我的观点:状态枚举仅对 Car 有意义。完全不同类型的对象会有完全不同的状态
  • 虽然它们会在不同的命名空间中,所以没关系
  • 想要在 Car 之外查看它的解释是有道理的。但就我而言,我有两个课程,ORCR。两者都有自己的一组状态,因此不能在自己的范围之外定义它们。
【解决方案4】:

我知道我的建议违反了 .NET 命名约定,但我个人用“E”为枚举添加前缀,用“F”为枚举标志添加前缀(类似于我们使用“I”为接口添加前缀的方式)。我真的不明白为什么这不是惯例。枚举/标志是一种特殊情况,例如永远不会改变其类型的接口。它不仅清楚地说明了它是什么,而且很容易输入智能感知,因为前缀将过滤大多数其他类型/变量/等,并且您不会遇到这些命名冲突。

这也将解决另一个问题,对于 WPF 中的示例,它们使用静态类,例如具有预定义类型实例的枚举(例如 FontWeights),但如果不搜索它,您将不知道。如果它们只是在它们前面加上“E”,那么您所要做的就是在字符上键入以找到这些特殊的静态类。

【讨论】:

    【解决方案5】:

    讨厌匈牙利符号及其变体的人该死。我使用枚举后缀的约定 - 等待它 - Enum。因此,我从来没有遇到过您描述的问题,浪费时间担心如何调用它们,并且代码是可读且可自我描述的。

    public class Car
    {
      public enum StatusEnum
      {
        Off,
        Starting,
        Moving
      };
    
      public StatusEnum Status { get; set; }
    
    }
    

    【讨论】:

    • 请注意,尽管 Microsoft 对 Naming Enumerations 的约定说:X DO NOT 在枚举类型中使用“枚举”后缀名字。
    • 因为微软的约定已被证明经得起时间的考验。
    【解决方案6】:

    我会将属性名称更改为“CurrentStatus”之类的名称。快速简单:)

    【讨论】:

      【解决方案7】:

      我建议在类型名称中添加“选项”(如果包含位标志,则添加标志),即类型为 Car.StatusOption,属性为 Car.Status。

      与复数相比,这避免了在创建枚举类型的集合时出现命名冲突,在这种情况下,您通常希望将集合 property 复数,而不是枚举 type

      【讨论】:

        【解决方案8】:

        我通常在枚举前面加上前缀,例如汽车状态。我想这一切都取决于您正在与之合作的团队(如果他们对这类事情有任何规则/流程)和对象的使用。只是我的 2 美分(:

        【讨论】:

        • 这实际上会破坏 MyObjectName 在 Status 前面的命名约定。
        • 类的命名空间应该足以处理这个问题
        猜你喜欢
        • 1970-01-01
        • 2010-11-27
        • 2011-03-05
        • 2015-11-21
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-01
        相关资源
        最近更新 更多