使用哈希码为枚举生成值

时间:2009-05-19 09:12:17

标签: c# enums

我们知道all enums are compiled as constants,这意味着如果您使用其他程序集中的枚举,则可以获得unexpected results

显式设置顺序枚举数没有帮助,因为如果你想为新值留出空间,你必须做基本的亚麻布式间距,这是naff。

所以我想知道将Enum值名称的哈希码用作字符串,这很容易生成脚本。

这是个好主意吗?我是否会遇到hashcode可以返回的负值的问题?

修改 对于那些问为什么的人,我引用了链接的“角落案例”:

给定一个程序集:

enum MyEnum
{
    Red,
    Blue,
}

如果你在另一个程序集中使用MyEnum.Red.ToString(),并且在某些时候有人将你的枚举重新编译为:

enum MyEnum
{
    Black,
    Red,
    Blue,
}

在运行时,你会得到“黑色”。

(注意,我对ToString并不特别感兴趣,问题是如果调用代码询问MyEnum.Red,它实际上是引用MyEnum.Black)

用显式顺序编号说明问题的另一个例子:

enum ECountry
{
    Afghanistan = 1,
    Barbados = 2,
    Chile = 3,
    ...
    Zambia = 243, 
}

如果Giggleswick突然宣布自己是共和国,你会怎么做?

4 个答案:

答案 0 :(得分:2)

不,这不是一个好主意。

您无法安全地从其哈希码重新创建字符串。您可以遍历名称并将其哈希代码与您拥有的代码进行比较,但由于哈希代码冲突,仍然存在误报的小风险。风险相当小,但它仍然不是一种可靠的使用方法。

如果需要从枚举的一个版本转换为另一个版本,请使用枚举值的名称。 ToString方法为您提供了名称,您可以使用Enum.Parse方法从字符串中获取枚举值。

编辑:
当然,使用字符串值要求每个程序集中都有一个枚举,以便每次都编译它。如果您在引用的程序集中使用枚举,那么您必须为每个值指定一个特定的数字表示,否则您根本没有任何东西可以保持从一个版本到下一个版本的值保持一致。

答案 1 :(得分:1)

您不会遇到负值问题。您可能会遇到重复值的问题,因为不保证字符串的哈希码是唯一的。

尽管如此,我宁愿将值明确地设置为1,2,3等等。

答案 2 :(得分:0)

两个不同字符串值的哈希码不保证是唯一的,因此这似乎是一个危险的选择。明确设置值有什么问题?除非数字在对象模型中有意义,否则似乎没有理由为新值留出空间 - 只需在枚举的末尾添加新选项。

答案 3 :(得分:0)

我不确定我是否误解了事情,但是......

MyEnum.Red.ToString()应该产生“Red”而不是0.因此,Enum.Parse应该没有正确的字符串评估。你要描述的问题是int Foo =(int)MyEnum.Red;哪个是0;这可能会导致在使用新元素重新编译后描述的结果不一致。

根据我对要求的理解,enum.ToString是持久的,应该没有问题。问题是持久化值或枚举,而不是字符串表示。因此,不需要散列。

这是一个例子(假装我们添加了黑色)......

 class Program
 {
  static void Main(string[] args)
  {
   // this is the approach described
   string RedToString = MyEnum.Red.ToString();

   // We're pretending that red was the zeroth element when we did (int)MyEnum.Red;
   int RedToInt = 0;

   MyEnum RedFromString = (MyEnum)Enum.Parse(typeof(MyEnum), RedToString);
   MyEnum RedFromInt = (MyEnum)RedToInt;

   // this is in theory how RedToInt was persisted
   int BlackFromInt = (int)MyEnum.Black;

   Console.WriteLine("RedToString: " + RedToString); // Red
   Console.WriteLine("RedToInt: " + RedToInt); // 0
   Console.WriteLine("RedFromString: " + RedFromString); // Red
   Console.WriteLine("RedFromInt: " + RedFromInt); // Black
   Console.WriteLine("BlackFromInt: " + BlackFromInt); // 0
   Console.Read();
  }

  enum MyEnum
  {
   Black,
   Red,
   Blue,
  }
 }

HTH, 本