为什么枚举有两个不同的名称具有相同的数值?

时间:2010-06-30 15:28:29

标签: c# enums

我刚刚发现了一个微妙的错误,我有一个枚举,两个名字无意中共享相同的数值(在这种情况下,红色= 10和深红色= 10)。我有点意外,这不是语法错误。

public enum Colour
{
    Red=10,
    Blue=11,
    Green=12,
    Crimson=10
}
// Debug.Write(Colour.Red==Colour.Crimson) outputs True

为什么这种行为可能有用或者认为它应该是语法错误,是否有任何现实世界的原因?

18 个答案:

答案 0 :(得分:38)

public enum Colour
{
    Red=10,
    Rouge=10,
    Blue=11,
    Bleu=11,
    Green=12,
    Vert=12,
    Black=13,
    Noir=13
}

答案 1 :(得分:24)

小心!如果您的enum包含多个具有相同值的元素,则在使用Enum.Parse()时可能会出现意外结果。这样做会随意返回具有请求值的第一个元素。例如,如果您有enum Car { Ford = 1, Chevy = 1, Mazda = 1},则(Car)Enum.Parse(typeof(Car), "1")将返回Car.Ford。虽然这可能有用(我不确定为什么会这样),但在大多数情况下,它可能会让人感到困惑(特别是对于维护代码的工程师),或者在出现问题时容易被忽视。

答案 2 :(得分:19)

我看到此功能有时用于“默认”值:

public enum Scope
{
    Transient,
    Singleton,
    Default=Transient
}

但要注意,这只是你的枚举用户的糖。仅仅因为它被称为默认,它并不意味着它是初始值。

答案 3 :(得分:10)

枚举与constans一样使用,你肯定可以有两个具有相同值的常量,它们在同一个地方使用。由于第三方API,它可能是这样,因为后向兼容性仅仅是因为业务规则。

答案 4 :(得分:7)

From the c# language spec

多个枚举成员可以共享相同的关联值。例子

enum Color 
{
    Red,
    Green,
    Blue,
    Max = Blue
}

显示一个枚举,其中两个枚举成员 - 蓝色和最大 - 具有相同的关联值。

在这种情况下,您可以检查MyColor == Color.Max,这在某些情况下会很有用。

答案 5 :(得分:4)

枚举是常量变量的枚举,你可以有两个具有相同值的项,我认为没有理由是语法错误,但是,这会导致此代码中的编译错误

switch(c)
{
  Colour.Red:
     break;
  Colour.Crimson:
     break;
  ...
}

答案 6 :(得分:3)

这不是语法错误。所有enum都以强类型的方式枚举一系列常量。

因此,如果开发人员输入错误(如在您的示例中),就CLR而言,这是一个非常有效的案例。 CLR假设开发人员知道他在做什么,以及他选择这样做的原因。

至于现实世界的情况,我无法想出任何关于时刻的事情,但我仍然确定在某些情况下它可能会有所帮助。

答案 7 :(得分:2)

当然有,虽然它可能不太常见。如果存在一个通常以两个不同名称知道的实体/值,那么这是一个很好的理由。

您提出的情景可能就是这种情况。直接来自BCL的更好的是System.Windows.Forms.MessageBoxIcon枚举; StopErrorHand成员都具有相同的描述且确实具有相同的值。 AsteriskInformation也是相同的,如评论所示:

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.

希望这可以让你对适当的场景有所了解(你自己可能是一个场景)。

答案 8 :(得分:1)

我目前正在开发一个项目,这实际上是一个有用的功能。

public enum State
{
    NotTransmitted = 0,
    Deleted = 0,
    Transmitted = 1,
    Deactivated = 1,
    Activated = 2
}

状态 NotTransmitted 和 Deleted 在编程上是相同的,对于实际情况的软件来说无关紧要。在这两种情况下,软件都必须 f.e.将此项目发送给接收方。

话虽如此,对于程序员来说,在删除之后将状态设置为“已删除”比将其设置为“未传输”要直观得多。传输后设置为“已传输”也是如此,将其设置为“已停用”。

简而言之,它增强了代码的可读性。

答案 9 :(得分:1)

此示例将说明这有用的原因。当您在致力于公共使用的公共图书馆工作时,以不同方式命名相同的内容可能会有用。

public enum GestureType
{
Touch = 1,
Tap = 1,
DoubleTouch = 2,
DoubleTap = 2,
Swipe = 3,
Slide = 3,
...
}

当某些情况下不同的词语具有相同的含义时,它们就有意义。在解析时,它总是在这种情况下返回良好的值。

答案 10 :(得分:1)

这是有效的,允许用不同的名称引用相同的值。 要注意这一点很有效。如果要从int / string转换为enum或格式化字符串,则可能会得到不一致的结果。

例如:

public enum Colour
{
    Red=10,
    Blue=11,
    Green=12,
    Crimson=10
}
Colour myColor = Colour.Crimson;
Console.WriteLine("Crimson is {0}", myColor.ToString());

输出:

Crimson is Red

答案 11 :(得分:1)

答案 12 :(得分:1)

使用命名值而不是实际值是root。假设您有相同的法语,英语等。这是我的枚举的根源。

答案 13 :(得分:1)

没关系。您可以有两个与API用户的观点不同的值,但在功能上可以视为相同的值。

答案 14 :(得分:0)

我认为重复使用相同数字有很多用途。举一个新的例子,假设你有一个排名系统,可以确保特定类(父)的对象在依赖它的其他类(子级)之前创建,你可能有一些孩子在同一个级别'并且首先创建哪一个并不重要。在下面的示例中,将首先创建Parent,然后创建Child 1,2或3,然后最后创建Child4。如果将其视为树形图,则具有相同编号的任何项目都将是“兄弟姐妹”。

public enum ObjectRanks
{
    Parent = 0,
    Child1 = 1,
    Child2 = 1,
    Child3 = 1,
    Child4 = 2
}

虽然我可以看到你的观点,但这可能很容易被误解。在这种情况下,如果visual studio有一个选项来启用警告可以让它编译,但如果两次使用相同的数字会发出警告,那将会很方便。

答案 15 :(得分:0)

我认为它对于字段映射很有用,例如(在LinqPad中):

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
}

目标是使用较短的名称,但是Parse或TryParse的结果不一致,并且此代码输出:

TaskName
TaskName
IsActive
IsActive

答案 16 :(得分:0)

    public enum SortBy
    {
        Ascending = 0,
        Descending = 1,
        Asc = 0,
        Desc = 1
    }

这就是为什么该解决方案对我有用的原因

答案 17 :(得分:0)

我在.net TWAIN包装器中看到了同样的东西 - 它允许所有TWAIN消息代码存储在一个大的枚举中,但它确实让事情有点混乱。