C# 为什么一个枚举可以有两个具有相同数值的不同名称?
我刚刚发现了一个微妙的错误,我有一个枚举,其中两个名称不必要地共享同一个数值(在本例中,red=10和crimson=10)。我有点惊讶这不是语法错误C# 为什么一个枚举可以有两个具有相同数值的不同名称?,c#,enums,C#,Enums,我刚刚发现了一个微妙的错误,我有一个枚举,其中两个名称不必要地共享同一个数值(在本例中,red=10和crimson=10)。我有点惊讶这不是语法错误 public enum Colour { Red=10, Blue=11, Green=12, Crimson=10 } // Debug.Write(Colour.Red==Colour.Crimson) outputs True 这个行为可能是有用的,或者确实认为它应该是语法错误,这有什么现实原因吗?枚举是常
public enum Colour
{
Red=10,
Blue=11,
Green=12,
Crimson=10
}
// Debug.Write(Colour.Red==Colour.Crimson) outputs True
这个行为可能是有用的,或者确实认为它应该是语法错误,这有什么现实原因吗?枚举是常量变量的枚举,您可以有两个值相同的项,我认为没有理由出现语法错误,但是,这将导致此代码中的编译错误
switch(c)
{
Colour.Red:
break;
Colour.Crimson:
break;
...
}
我在.net TWAIN包装器中也看到了同样的情况-它允许所有TWAIN消息代码存储在一个大的枚举中,但一开始确实会让事情变得有点混乱。枚举的使用方式与constans类似,您肯定可以在相同的位置使用两个具有相同值的常量。这可能是因为第三方API,因为向后兼容性,而不仅仅是因为业务规则。没关系。您可以有两个不同于API用户观点的值,但在功能上可以视为相同的值。这不是语法错误。
enum
所做的就是以强类型方式枚举一系列常量
public enum Colour
{
Red=10,
Rouge=10,
Blue=11,
Bleu=11,
Green=12,
Vert=12,
Black=13,
Noir=13
}
因此,如果开发人员键入错误(如您的示例中),就CLR而言,这是一种完全有效的情况。CLR假设开发人员知道自己在做什么,以及为什么选择这样做
至于现实世界中的案例,我一时冲动想不出什么,但我仍然确信,在某些情况下,它可能会有所帮助。当然会有,尽管它可能不太常见。如果有一个实体/值通常以两个不同的名称命名,那么这就是一个很好的理由 您所介绍的场景可能就是这样一种情况。一个更好的,直接来自BCL的,是enum;
Stop
、Error
和Hand
成员都具有相同的描述和值<代码>星号和信息
也完全相同,如注释所示:
Asterisk The message box contains a symbol consisting of a lowercase letter i in a circle.
Information The message box contains a symbol consisting of a lowercase letter i in a circle.
希望这能让您对合适的场景有一个很好的了解(您自己可能就是其中之一)。我已经看到此功能有时用于“默认”值:
但请注意,这只是enum用户的糖分。仅仅因为它被称为默认值,并不意味着它是初始值。使用按命名值而不是实际值是根。假设你有法语、英语等具有相同值的语言。对我来说,这是enum的根。: 多个枚举成员可以共享相同的关联值。榜样
enum Color
{
Red,
Green,
Blue,
Max = Blue
}
显示两个枚举成员Blue和Max具有相同关联值的枚举
在这种情况下,您可以检查MyColor==Color.Max,这在某些情况下会很有用。有时建议(尽管MS不建议使用C#!——请参阅Salaros的评论)在枚举中包括一个下限和上限,例如
public enum Colour
{
LowBound=10,
Red=10,
Rouge=10,
Blue=11,
Bleu=11,
Green=12,
Vert=12,
Black=13,
Noir=13,
UpperBound=13
}
为了验证/迭代每个可能的设置。尽管我有一种感觉,.Net可能为此提供了一种工具:)我认为重复使用同一个数字有很多用途。举一个新的例子,假设您有一个排名系统,该系统将确保特定类(父类)的对象在依赖于它的其他类(子类)之前创建,您可能有一些子类位于同一“层”,而先创建哪个并不重要。在下面的示例中,将首先创建父级,然后创建子级1、2或3,最后一个是子级4。如果将其视为树形图,则任何具有相同编号的项都将是“兄弟”
public enum ObjectRanks
{
Parent = 0,
Child1 = 1,
Child2 = 1,
Child3 = 1,
Child4 = 2
}
虽然我能理解你的观点,这很容易出错。在这种情况下,如果VisualStudio有一个选项可以启用警告,它将允许编译,但如果相同的数字被使用两次,它将发出警告。小心!如果
enum
具有多个具有相同值的元素,则在使用enum.Parse()时可能会得到意外的结果。这样做将任意返回具有请求值的第一个元素。例如,如果您有enum Car{Ford=1,Chevy=1,Mazda=1}
,那么(Car)enum.Parse(typeof(Car),“1”)
将返回Car.Ford
。虽然这可能有用(我不确定为什么会有用),但在大多数情况下,这可能会让人困惑(尤其是对于维护代码的工程师),或者在出现问题时容易被忽略。这是有效的,允许使用不同的名称引用相同的值。
注意,这种方法在一个方面效果很好。如果从int/string转换为enum或格式化字符串,可能会得到不一致的结果
例如:
输出:
Crimson is Red
这个例子将说明为什么这是有用的。当你们在公共图书馆工作时,用不同的方式命名相同的东西可能会很有用
public enum GestureType
{
Touch = 1,
Tap = 1,
DoubleTouch = 2,
DoubleTap = 2,
Swipe = 3,
Slide = 3,
...
}
当不同的词在某些情况下有相同的意思时,命名它们是有意义的。解析时,在这种情况下它总是返回良好的值。我认为它对于字段映射很有用,例如(在LinqPad中):
目的是使用较短的名称,但是Parse或TryParse的结果不一致,此代码输出:
TaskName
TaskName
IsActive
IsActive
这就是为什么这个解决方案对我很有用的原因值得知道这一点。这是一个不故意使用股票名称的理由;具有相同值的两个名称不是错误。如果您想避免,请不要指定数值。您将如何使用它?在一个多语言编程团队中,每个成员都在选择自己的常量?我不知道这是一个怎样的有效答案。@Robin:就像@Noldorin一样,我看不出这有什么用处。你能举一个使用它的例子吗?罗宾,好的,但是OQ是为什么它是w
public enum GestureType
{
Touch = 1,
Tap = 1,
DoubleTouch = 2,
DoubleTap = 2,
Swipe = 3,
Slide = 3,
...
}
void Main()
{
((FieldName)Enum.Parse(typeof(FieldName), "Name", true)).ToString().Dump();
((FieldName)Enum.Parse(typeof(FieldName), "TaskName", true)).ToString().Dump();
((FieldName)Enum.Parse(typeof(FieldName), "IsActive", true)).ToString().Dump();
((FieldName)Enum.Parse(typeof(FieldName), "TaskIsActive", true)).ToString().Dump();
}
public enum FieldName
{
Name,
TaskName = Name,
IsActive,
TaskIsActive = IsActive
}
TaskName
TaskName
IsActive
IsActive
public enum SortBy
{
Ascending = 0,
Descending = 1,
Asc = 0,
Desc = 1
}