2016-05-12 3 views
1

Я определил enum с атрибутом [Flag].Использование Where on Enum Values ​​

Учитывая целочисленное значение, я хотел бы напечатать все значения enum для битов, установленных в целочисленном значении.

Вот что у меня есть.

string s = string.Join(", ", Enum.GetValues(typeof(MyEnumType)).OfType<Enum>() 
           .Where(x => (MyIntValue & (int)x) != 0)); 

Но напечатанный на int в последней строке дает мне следующую ошибку.

Невозможно преобразовать тип «System.Enum» в «» междунар

Я желаю Microsoft заменит все Рамочную код, который возвращает Array в пользу типов, которые поддерживают LINQ.

Но есть ли простой способ сделать это?

+1

Почему не делают '.OfType ()' вместо '.OfType ()'? –

+0

листинг вашего значения int для Enum и вызов ToString() должны делать именно то, что вы хотите. См. Http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c?rq=1 – devio

+0

«Я хочу, чтобы Microsoft заменила весь код Framework, который возвращает Array в пользу типов, поддерживающих LINQ. " - и что они должны делать со всем устаревшим кодом, который был написан до Linq? Просто пусть весь этот код, разработанный за эти годы, внезапно сломается? –

ответ

2

Слишком много LINQ способ мышления, так что иногда мы забываем, откуда мы пришли :) Начиная с самой первой версии .NET, Enum.GetValues(typeof(MyEnum)) фактически возвращает MyEnum[], так что вам не нужно ни OfType, ни Cast, но просто C# cast:

string s = string.Join(", ", ((MyEnum[])Enum.GetValues(typeof(MyEnumType))) 
    .Where(x => (MyIntValue & (int)x) != 0)); 

Так что typeof в сочетании с литьем к тому же типу очень раздражает, от очень долгого времени, у меня есть этот маленький помощник в моем кармане:

public static class EnumInfo 
{ 
    public static T[] GetValues<T>() where T : struct // I (and not only) wish I could say where T : enum 
    { 
     return (T[])Enum.GetValues(typeof(T)); 
    } 
} 

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

string s = string.Join(", ", EnumInfo.GetValues<MyEnumType>() 
    .Where(x => (MyIntValue & (int)x) != 0)); 
+0

Должен ли ваш метод GetValues ​​() 'возвращать нечто, отличное от' T'? Например, 'T []'? –

+0

@JonathanWood Абсолютно, спасибо (вы знаете, как это происходит, когда вы пишете код непосредственно в браузере :) –

3

Кастинг в MyEnumType вместо родового Enum должен решить проблему:

string s = string.Join(
    ", ", 
    Enum.GetValues(typeof(MyEnumType)) 
     .OfType<MyEnumType>() 
     .Where(x => (MyIntValue & (int)x) != 0)); 

Вы должны действительно использовать Cast вместо OfType, так как вы уверены, что детали типа MyEnumType.

+0

Да, ты прав. Этот код все еще слишком грязный и работает слишком медленно. Microsoft должна обновить Framework. Благодарю. –

+0

Добро пожаловать –

+0

@JonathanWood Какая часть выполняет «слишком медленно» и как вы предлагаете Microsoft исправить ее? –

0

Вы можете написать свой собственный метод GetValues, который использует дженерики, чтобы получить то, что вам нужно:

public static class EnumUtil 
{ 
    public static IEnumerable<T> GetValues<T>() 
    { 
     foreach(T enumVal in Enum.GetValues(typeof(T))) 
     { 
      yield return enumVal; 
     } 
    } 
} 

, который затем используется как так:

var s = string.Join(", ", EnumUtil.GetValues<TestEnum>() 
    .Where(x => (myIntValue & (int)x) != 0));