2014-11-21 6 views
0

Есть несколько других вопросов о том, как конвертировать перечисления и что происходит, если значение разобрано выходит за пределы диапазона, как в:Проверьте, если значение находится в диапазоне Enum без использования IsDefined

public enum SomeTypes 
{ 
    SomeType1 = 1, 
    SomeType2 = 2, 
    SomeType3 = 3 
} 

public class SomeClass 
{ 
    ... 
    var inRange = (SomeTypes) 1; 
    var outOfRange = (SomeTypes) 5; 
    ... 
} 

Выход из диапазона не приведет к какой-либо ошибке. Но я нашел трудный путь, что если вы попытаетесь сериализовать-десериализовать перечисление с внеземным значением, вы получите странные ошибки. Например, я получаю что-то вроде

«Ошибка синтаксического анализа сообщения или тайм-аут превышен»

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

Предложения по его устранению можно получить с помощью Enum.IsDefined. Это, кажется, работает довольно хорошо, но есть это довольно смелое предупреждение о msdn:

«Не используйте System.Enum.IsDefined (System.Type, System.Object) для проверки диапазона перечисления, поскольку она основана на тип времени выполнения перечисления, который может меняться от версии к версии ».

Итак, мой вопрос, мы можем смело использовать Enum.IsDefined или что это правильный способ проверить, если значение перечисления выходит за пределы диапазона без использования Enum.IsDefined?

+0

Используйте 'Enum.GetValues', найдите min и max of this , Затем вы можете легко проверить, находится ли значение в диапазоне или нет. Если курс, эта идея не будет работать для бит-флагов. –

+1

Добавьте 'Parse()' или 'TryParse()' метод и используйте это вместо простого кастинга. – BCdotWEB

+2

Это предупреждение основано на предположении, что декларация перечисления не совпадает с кодом проверки. Другими словами, более поздняя версия кода может добавлять дополнительные члены перечисления, но код, который использует перечисление, не был обновлен, чтобы справиться с этим. Может случиться, но вряд ли применим к вашему делу. Большая проблема заключается в том, что когда вы избегаете IsDefined, у вас будет новая ошибка в вашем коде. Поэтому игнорируйте этот совет. –

ответ

0

Я сделал аналогичную вещь с объектами DataContract Вы должны украсить элементы в списке [EnumMember], а затем вы можете получить имя перечисления с помощью этого метода. Таким образом, вы знаете, существует ли значение в enum cos, возвращает его имя перечисления.

public static string GetEnumNameFromValue(System.Type typeEnum, string value) 
     { 
      FieldInfo[] fis = typeEnum.GetFields(); 
      foreach (FieldInfo fi in fis) 
      { 
       EnumMemberAttribute[] attributes = (EnumMemberAttribute[])fi.GetCustomAttributes(typeof(EnumMemberAttribute), false); 
       if (attributes.Length > 0) 
       { 
        if (string.Compare(attributes[0].Value, value, true) == 0) 
        { 
         return fi.Name; 
        } 
       } 
      } 
      return null; 
     } 
1

Использование Enum.GetValues():

public bool IsInRange(int value){ 
    var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x); 

    return value >= values.First() && value <= values.Last(); 
} 

[EDIT]

В случае, если вы хотите проверить, если элемент определен вместо того, чтобы просто проверить, если он находится внутри диапазона, вы можете сделать аналогичным образом:

public bool IsDefined(int value){ 
    var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x); 

    return values.Contains(value); 
} 
+0

Это, вероятно, сработает, но добавляет скрытое ограничение, что я задаюсь вопросом, будет ли это очевидно, если в будущем кто-то добавит не-последовательные значения перечисления. , – nando

Смежные вопросы