Вопрос по silverlight – Итерация по перечислению в Silverlight?

31

В .Net можно перебирать перечисление, используя

<code>System.Enum.GetNames(typeof(MyEnum)) 
</code>

или же

<code>System.Enum.GetValues(typeof(MyEnum))
</code>

В Silverlight 3, однако, Enum.GetNames и Enum.GetValues не определены. Кто-нибудь знает альтернативу?

Смешно, что это не в рамках. Размер загрузки не является оправданием для пыток разработчиков. Bryan Legend
если кому-то нужны, в частности, GetEnumValues () и GetEnumNames (); Я реализовал их (основываясь на ответе ptoinson и Shimmy ниже) как ответ на следующий вопрос: / Stackoverflow.com вопросы / 7062208 / ..., и я думаю, что они эквивалентны обычным (но не Silverlight) .NET-функциям с тем же именем. shelleybutterfly

Ваш Ответ

3   ответа
30

    public static T[] GetEnumValues<T>()
    {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException("Type '" + type.Name + "' is not an enum");

        return (
          from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
          where field.IsLiteral
          select (T)field.GetValue(null)
        ).ToArray();
    }

    public static string[] GetEnumStrings<T>()
    {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException("Type '" + type.Name + "' is not an enum");

        return (
          from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
          where field.IsLiteral
          select field.Name
        ).ToArray();
    }
Лучше поставитьwhere T : struct,IConvertible в определении метода, чтобы приблизиться к ограничениюT только для перечислений. Kamyar
27

как это сделать, не делая предположений о перечислении, имитируя функции в .Net:

public static string[] GetNames(this Enum e) {
    List<string> enumNames = new List<string>();

    foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)){
        enumNames.Add(fi.Name);
    }

    return enumNames.ToArray<string>();
}

public static Array GetValues(this Enum e) {
    List<int> enumValues = new List<int>();

    foreach (FieldInfo fi in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)) {
        enumValues.Add((int)Enum.Parse(e.GetType(), fi.Name, false));
    }

    return enumValues.ToArray();
}
Хорошее решение +1! stevehipwell
Я, однако, предложил бы, чтобы вы вернули IList <string> для верхнего метода и IList <int> для второго. И напомним, ember, что это не будет поддерживать перечисления, представляющие длинное значение. stevehipwell
Вы можете поддерживать не-int типы, получая базовый тип (Enum.GetUnderlyingType ()) dcstraw
Это решение оставляет желать лучшего. Синтаксис использования требует, чтобы вы предоставили экземпляр типа перечисления, в то время как оригинальные методы .net позволяют вам напрямую работать с типом. В этом отношении я нахожу ответ @ptoinson лучше. Его синтаксис прост и понятен. GetEnumValues <MyEnumType> () angularsen
1

что это то же самое, что и в .NET Compact Framework. Если мы сделаем предположение, что ваши значения enum начинаются с 0 и используют каждое значение до тех пор, пока их диапазон не будет превышен, следующий код должен работат

public static IList<int> GetEnumValues(Type oEnumType)
{
  int iLoop = 0;
  bool bDefined = true;
  List<int> oList = new List<int>();

  //Loop values
  do
  {
    //Check if the value is defined
    if (Enum.IsDefined(oEnumType, iLoop))
    {
      //Add item to the value list and increment
      oList.Add(iLoop);
      ++iLoop;
    }
    else
    {
      //Set undefined
      bDefined = false;
    }
  } while (bDefined);

  //Return the list
  return oList;
}

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

Вот альтернативная версия метода, который возвращаетIList<EnumType>.

public static IList<T> GetEnumValues<T>()
{
  Type oEnumType;
  int iLoop = 0;  
  bool bDefined = true;  
  List<T> oList = new List<T>();  

  //Get the enum type
  oEnumType = typeof(T);

  //Check that we have an enum
  if (oEnumType.IsEnum)
  {
    //Loop values  
    do
    {
      //Check if the value is defined    
      if (Enum.IsDefined(oEnumType, iLoop))
      {
        //Add item to the value list and increment      
        oList.Add((T) (object) iLoop);
        ++iLoop;
      }
      else
      {
        //Set undefined      
        bDefined = false;
      }
    } while (bDefined);
  }

  //Return the list  
  return oList;
}
Я знаю, что у вас есть предостережение о принятии смежных значений, но, в частности, любые перечисленные [Flags] перечисления не сработают. dcstraw
Запрос, если вы не возражаете: поскольку он не возвращает массив определенных перечислимых типов, но вместо этого List <int>, он на самом деле не соответствует поведению на платформе .NET и вызвал немало путаницы для меня при попытке определить, будет ли эта функция работать для другого пользователя. Будете ли вы готовы переименовать его в другое? Основная проблема для меня заключалась в том, что GetArrayValues (i) .ToString () возвращает строку с числом, а не именем перечисления, как это было в реальной версии .NET, хотя я уверен, что существуют и другие возможные источники путаницы. shelleybutterfly
@ dcstraw - прочитайте последнюю отправку, я подтвердил, что вы можете использовать другой шаблон для сопоставления побитовых значений, например [Флаги]; сделать это++iLoop; становитсяiLoop = iLoop << 1;. stevehipwell
Так как в случае спрашивающего EnumType не был известен заранее; только, скажем,Type CurrentEnumType; было дано. И я согласен, что вы адекватно разъяснили это в последующем тексте, просто это было источником путаницы для меня (который не был знаком с обычным возвращаемым значением; массив, содержащий какие-либо типы перечислений), потому что я предполагал то, что такое же имя означало, что оно возвращало то же самое, что и стандартный метод .NET framework. shelleybutterfly
@ shelleybutterfly - Почему бы не использовать((EnumType)GetArrayValues[i]).ToString() или в VB.NETCType(GetArrayValues(i), EnumType).ToString()? В моем ответе говорится, что приведенный выше код является простым примером, и его можно легко переписать, чтобы он возвращал другой тип или соответствовал другому шаблону перечисления. stevehipwell

Похожие вопросы