C#的枚举和匹配属性的命名约定
我经常发现自己实现了一个类,把某种自己的状态属性作为一个枚举:我有一个Status枚举和一个状态types的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(); } } }
如果状态枚举对于不同types是通用的,我会把它放在课堂外面,问题就解决了。 但状态只适用于汽车,因此在课堂外申报枚举是没有意义的。
你在这种情况下使用什么命名约定?
注:这个问题在回答这个问题的意见中部分辩论过。 由于这不是主要问题,所以没有得到太多的知名度。
编辑:菲利普Ekbergbuild议国际海事组织优秀的解决scheme,为'状态'的具体情况。 不过,如果你想知道枚举/属性名称不同的解决scheme,那么我会很有兴趣的,正如Michael Prewecki的回答 。
EDIT2(2010年5月):我最喜欢的解决scheme是复用枚举types名称,如Chris S.所build议。根据MS指南,这应该只用于标志枚举。 但是我越来越喜欢它了。 我现在也用它来定期枚举。
我会加1欧元的讨论,但它可能不会增加任何新的东西。
显而易见的解决scheme是将状态移出嵌套枚举。 大多数.NET枚举(除了可能在Windows.Forms命名空间中的一些)都不是嵌套的,它使得开发人员使用API时很烦人,必须在类名的前面加上前缀。
有一点没有提到的是,根据MSDN指南的标志枚举应该是你可能已经知道的复数名词 (状态是一个简单的枚举,所以应该使用单数名词)。
国家(enum称为国家)是呼吁,“地位”是一个名词的主格,英语像大多数我们的语言从拉丁文吸收。 Vocative是你命名一个名词的状态,主格是动词的主语。
所以换句话说,当汽车移动时 ,这就是动词 – 移动是它的状态。 但是汽车不熄火,它的发动机。 它也不是开始,发动机(你可能在这里select一个例子,所以这可能是无关紧要的)。
public class Car { VehicleState _vehicleState= VehicleState.Stationary; public VehicleState VehicleState { get { return _vehicleState; } set { _vehicleState = value; DoSomething(); } } } public enum VehicleState { Stationary, Idle, Moving }
国家是这样一个广义的名词,描述它所指的是什么状态不是更好吗? 就像我上面做的那样
在我看来,types的例子并不是指读者types,而是数据库。 如果您描述的读者的数据库产品与阅读器的types不一定相关(例如,阅读器的types可能只是转发,caching等),我更喜欢它。 所以
reader.Database = Databases.Oracle;
实际上,这不会发生,因为它们被实现为驱动程序和inheritance链,而不是使用枚举,这就是为什么上面的行看起来不自然。
“关”,“开始”和“移动”的定义就是我所说的“国家”。 而当你暗示你正在使用“国家”时,这是你的“身份”。 所以!
public class Car { public enum State { Off, Starting, Moving }; State state = State.Off; public State Status { get { return state ; } set { state= value; DoSomething(); } } }
如果我们再举一个例子,在这种情况下你想使用“types”这个词:
public class DataReader { public enum Type { Sql, Oracle, OleDb } public Type Type { get; set; } // <===== Won't compile ===== }
你真的需要看到,枚举和枚举是有区别的,对吗? 但是当创build一个框架或者谈论架构时,你需要把注意力放在相似性上,好吧,让我们find它们:
当一个国家被设置时,它被定义为“事物”状态
例如:汽车状态处于运行状态,停止状态等。
在第二个例子中你想达到的是这样的:
myDataReader.Type = DataReader.Database.OleDb
你可能会认为这与我一直在向别人讲道的内容是一致的,你需要遵循一个标准。 但是,你正在遵循一个标准! Sql-case也是一个特例,因此需要一些具体的解决scheme。
但是,枚举将在您的System.Data
空间内重用,这就是模式的全部内容。
另一个与“types”相关的案例是“Animal”,其中Type定义了种类。
public class Animal { public enum Type { Mammal, Reptile, JonSkeet } public Type Species{ get; set; } }
这是遵循一个模式,你没有具体需要“知道”这个对象,你没有指定“AnimalType”或“DataReaderType”,你可以在你select的命名空间中重新使用枚举。
我认为这里真正的问题是枚举状态被封装在你的类中,所以Car.Status
对属性Status
和枚举Status
都是不明确的
更好的是,把你的enum放在课外:
public enum Status { Off, Starting, Moving } public class Car { public Status Status { ... } }
UPDATE
由于下面的评论,我会解释我的devise上面。
我不认为枚举或类或任何其他对象应该驻留在另一个类中,除非在这个类中是完全私有的。 以上面的例子为例:
public class Car { public enum Status {...} ... public Status CarStatus { get; set;} }
虽然一些评论者会认为Status没有超出Class Car范围的意思,但是您设置公共财产的事实意味着该程序的其他部分将使用该枚举:
public Car myCar = new Car(); myCar.CarStatus = Car.Status.Off;
而这对我来说是一种代码味道。 如果我要去看Car
外的那个地位,我也可以在外面定义它。
因此,我可能会将其重命名为:
public enum CarStatus {...} public class Car { ... public CarStatus Status { get; set; } }
但是,如果这个枚举将被使用, 并且只能在车内使用,那么我可以在那里声明枚举。
我知道我的build议是违背了.NET命名约定,但是我个人使用'E'作为枚举前缀,使用'F'作为枚举标志(类似于我们如何在Interfaces前加上'I')。 我真的不明白为什么这不是公约。 枚举/标志是像接口这样的特殊情况,永远不会改变它们的types。 它不仅可以清楚地说明它是什么,而且键入intellisense非常容易,因为前缀会过滤大多数其他types/variables/等,而且不会出现这些命名冲突。
这也解决了另外一个问题,例如在WPF中,他们使用静态类,比如枚举types(例如FontWeights),它们有预定义的types实例,但不知道是否不search。 如果他们只是用“E”作为前缀,那么你所要做的就是input字符来查找这些特殊的静态类。
我会改变属性的名称像“CurrentStatus”。 快速简单:)
匈牙利符号的仇恨者及其变体将被诅咒。 我使用后缀枚举约定 – 等待它 – Enum
。 因此,我从来没有遇到过你所描述的问题,浪费时间担心应该怎么称呼它们,而代码是可读的,并且是自描述性的以便引导。
public class Car { public enum StatusEnum { Off, Starting, Moving }; public StatusEnum Status { get; set; } }
我build议添加“选项”的types名称(或标志,如果它包含位标志),即types是Car.StatusOption和属性是Car.Status。
与复数forms相比,这样做避免了在创build枚举types集合时的命名冲突,您通常希望复制集合属性 ,而不是枚举types 。
我通常以枚举为前缀,例如CarStatus。 我想这一切都取决于你正在使用的团队(如果他们有这样的事情的任何规则/进程)和对象的使用情况。 只是我2美分(: