ChatGPT解决这个技术问题 Extra ChatGPT

枚举和匹配属性的 C# 命名约定

我经常发现自己实现了一个类,它维护某种自己的状态属性作为枚举:我有一个 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 指南,这应该仅用于标志枚举。但我越来越喜欢它了。我现在也将它用于常规枚举。

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

F
Filip Ekberg

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

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 样本准确地指出了我在第一条评论中的意思,即这几乎是枚举的“改写”。我认为,使用枚举和属性名称的同义词会使代码有些混乱。
我也认为“物种”只是类型的改写(在这种情况下是动物)。
简单地重命名并不总是那么干净 - 例如考虑一个扑克牌的类,带有枚举套装和属性套装 - 重命名到底是什么?无论哪种方式都笨拙。
这种方法会导致误解和混淆代码
T
Trisped

我会在讨论中添加我的 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
}

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

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

reader.Database = Databases.Oracle;

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


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

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

更好的是,将您的枚举放在课堂之外:

public enum Status
{
    Off,
    Starting,
    Moving
}

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

更新

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

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

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

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

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

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

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

public enum CarStatus
{...}

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

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


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

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

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


n
nathanchere

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

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

  public StatusEnum Status { get; set; }

}

请注意,尽管 Microsoft 对 Naming Enumerations 的约定说:X DO NOT 在枚举类型名称中使用“Enum”后缀。
因为微软的约定已被证明经得起时间的考验。
T
TWith2Sugars

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


K
Kristian Wedberg

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

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


K
Kieron

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


这实际上会破坏在 Status 前面具有 MyObjectName 的命名约定。
无论如何,类中的命名空间应该足以处理这个问题

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅