Использование хеш-кода для генерации значения для enum - PullRequest
0 голосов
/ 19 мая 2009

Как мы знаем, все перечисления скомпилированы как константы , что означает, что вы можете получить неожиданные результаты , если вы используете перечисление из другой сборки.

Установка последовательных числовых чисел в явном виде не поможет, потому что, если вы хотите оставить место для новых значений, вы должны сделать интервал в стиле базового белья, который не имеет значения.

Так что мне стало интересно, как использовать хеш-код имени значения Enum в качестве строки, для чего довольно просто создать сценарий.

Это хорошая идея? Будут ли у меня проблемы с отрицательными значениями, которые может вернуть хэш-код?

EDIT Для тех, кто спрашивает, почему, я цитирую связанный "угловой случай":

Учитывая сборку с:

enum MyEnum
{
    Red,
    Blue,
}

если вы используете MyEnum.Red.ToString () в другой сборке, а между тем кто-то перекомпилировал ваше перечисление в:

enum MyEnum
{
    Black,
    Red,
    Blue,
}

во время выполнения вы получите «черный».

(NB, меня здесь не особо интересует ToString, проблема в том, что если вызывающий код запрашивает MyEnum.Red, он фактически ссылается на MyEnum.Black)

Еще один пример, иллюстрирующий проблему с явной последовательной нумерацией:

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

Если Гигглсвик вдруг объявит себя республикой, что вы будете делать?

Ответы [ 4 ]

2 голосов
/ 19 мая 2009

Нет, это не очень хорошая идея.

Вы не можете безопасно воссоздать строку из ее хеш-кода. Вы можете циклически просматривать имена и сравнивать их хеш-код с тем, который у вас есть, но все еще существует небольшой риск ложного срабатывания из-за коллизий хеш-кода. Риск довольно мал, но это все еще не надежный метод для использования.

Просто используйте имя значения перечисления, если вам нужно преобразовать одну версию перечисления в другую. Метод ToString дает вам имя, и вы можете использовать метод Enum.Parse, чтобы получить значение enum из строки.

Edit:
Конечно, для использования строкового значения необходимо, чтобы в каждой сборке было одно вхождение перечисления, чтобы оно компилировалось каждый раз. Если вы используете перечисление в сборке, на которую ссылаются, то вы должны присвоить каждому значению конкретное числовое представление, иначе у вас вообще ничего не будет, что сохраняло бы значение согласованным от одной версии к следующей.

1 голос
/ 19 мая 2009

У вас не будет проблем с отрицательными значениями. У вас могут быть проблемы с дублирующимися значениями, поскольку хеш-код для строки не обязательно будет уникальным.

Хотя я бы предпочел просто явно установить значения 1, 2, 3 и т. Д.

0 голосов
/ 10 октября 2009

Я не уверен, что неправильно понимаю, или нет, но ..

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,
  }
 }

НТН, Ben

0 голосов
/ 19 мая 2009

Хеш-код двух разных строковых значений не гарантированно является уникальным, поэтому это кажется опасным вариантом. В чем проблема с настройкой значений явно? Если числа не имеют смысла в вашей объектной модели, то, по-видимому, нет причин оставлять место для новых значений - просто добавьте новые опции в конец перечисления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...