【问题标题】:When are two enums equal in C#?C# 中两个枚举何时相等?
【发布时间】:2009-11-06 09:08:44
【问题描述】:

我创建了两个枚举,我知道它们不是 same,但我仍然认为它们是有道理的,因为它们的字符串表示形式以及它们的数字表示是相等的(甚至是相同的......)。

换句话说:我希望第一个测试通过,第二个测试失败。然而实际上,他们都失败了。所以:C# 中的两个枚举何时相等?或者无论如何要在 C# 中定义等号运算符?

谢谢!

    public enum enumA {one, two}

    public enum enumB {one, two}

    [Test]
    public void PreTest()
    {           
    Assert.AreEqual(enumA.one,enumB.one);
    Assert.AreSame(enumA.one, enumB.one);
    }

更新:1)所以到目前为止所有的答案都是比较表示,无论是整数还是字符串。我收集的枚举本身总是不相等?没有办法为它定义平等?

【问题讨论】:

标签: c# enums equality


【解决方案1】:

枚举在 C# 中是强类型的,因此是 enumA.one != enumB.one。现在,如果您将每个枚举转换为它们的整数值,它们将是相等的。

Assert.AreEqual((int)enumA.one, (int)enumB.one);

另外,我想质疑这样一种说法,即因为它们具有相同的整数或字符串表示形式,所以它们应该相同或等于。给定两个枚举NetworkInterfaceVehicleType,C# 或 .Net 框架允许NetworkInterface.None 在作为枚举比较时,通过值或字符串等于VehicleType.None 是不合逻辑的。但是,如果开发人员将强类型枚举转换为整数或字符串,则语言或框架无法阻止两者相等。

为了进一步澄清,您不能覆盖 MyEnum.Equals 以提供不同的相等方法。 .Net 枚举并不是 Java 更高版本中的一等公民,我希望 C# 允许与枚举进行更丰富的交互。

【讨论】:

  • 这里要小心,这只有在序数位置相同时才成立。
  • 谢谢。但是 != 运算符不是我所追求的,而是 equals()。我认为即使是不同的强类型类型也可以相等,或者这不是真的吗?
  • @Peter:枚举是结构,此外,您不能重载它们的任何方法。我也使用 != 作为动词,而不是实际的代码 sn-p。 @Tim:确实,这仅适用于他的情况和他的情况。
  • 枚举是值类型,以澄清我的上述内容。
  • MS 为虚拟Equals(Object) 方法使用了与特定类型重载相同的名称,这太糟糕了;如果前者被命名为EquivalentTo,事情会更清楚。事实上,Equals 仅在将操作数强制转换为 Object 时才定义等价关系。否则,(4.0).Equals(4.0f) 为真 [4.0f 被转换为并比较为double],但 (4.0f).Equals(4.0) 为假 [4.0 被转换为并比较为,Object]。类似的情况适用于比较枚举类型和整数。
【解决方案2】:

我建议您参考 C# 语言规范 v3.0,此引文摘自第 29 页的枚举部分:

“每个枚举类型都有一个对应的整数类型,称为枚举类型的基础类型。没有显式声明基础类型的枚举类型具有 int 基础类型。枚举类型的存储格式和可能值的范围是由其基础类型确定。枚举类型可以采用的值集不受其枚举成员的限制。特别是,枚举的基础类型的任何值都可以强制转换为枚举类型,并且是一个不同的有效值那个枚举类型。”

.AreEqual 方法实际上是在测试等价性,而第二个方法是在测试身份。因此,只需将每个类型转换为其底层类型(在本例中为 int),然后进行比较。

public enum enumA { one, two }
public enum enumB { one, two }
[Test]
public void PreTest()
{
        Assert.AreEqual((int)enumA.one,(int)enumB.one);
        Assert.AreSame(enumA.one, enumB.one);
}

【讨论】:

    【解决方案3】:

    与 Java 不同,C# 不提供任何向枚举添加方法(例如 operator==())的工具。

    我过去在需要更智能的枚举时所做的是创建一个XHelper 类(其中X 是枚举的名称),然后我将所有方法都放在它上面。因此是这样的:

    public static bool EnumAHelper.EqualsEnumB(EnumA enumA, EnumB enumB)
    {
        return (int)enumA == (int)enumB;
    }
    

    不过,我不记得遇到过需要两个不同枚举来表示同一事物的情况。

    【讨论】:

    • 非常好的评论(虽然之后)。我正在重写一个我想要兼容的现有类,所以它的枚举也应该是相同的。
    【解决方案4】:

    如果您希望它们匹配,请将它们转换为 int

    Assert.AreEqual((int)enumA.one,(int)enumB.one);
    

    会通过,因为它们都是第一个列出的。如果您希望它们匹配,因为它们都说“一”,那么您需要使用反射。

    【讨论】:

    • 我认为,您可以这样做来检查字符串值:Assert.AreEqual(enumA.one.ToString(), enumB.one.ToString());
    【解决方案5】:

    说实话,大多数时候,平等并不是直截了当的。

    我倾向于创建一个实现 IEqualityComparer(以及任何其他相等性测试,例如 IsSame())的辅助类并使用它。

    【讨论】:

      【解决方案6】:
          public enum enumA {one = 1, two = 2}
      
          public enum enumB {one = 1, two = 2}
      
          [Test]
          public void PreTest()
          {                       
              Assert.AreEqual((int)enumA.one, (int)enumB.one);
              // I don't think this one will ever pass
              Assert.AreSame(enumA.one, enumB.one); 
          }
      

      【讨论】:

        【解决方案7】:

        您可以尝试投射它们:

        Assert.AreEqual((int)enumA.one, (int)enumB.one);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多