как проверить, находится ли строковое значение в списке Enum?

92

В моей строке запроса есть переменная возраста ?age=New_Born.

Есть ли способ проверить, находится ли это строковое значение New_Bornв моем списке Enum

[Flags]
public enum Age
{
    New_Born = 1,
    Toddler = 2,
    Preschool = 4,
    Kindergarten = 8
}

Я мог бы использовать оператор if прямо сейчас, но если мой список Enum станет больше. Я хочу найти лучший способ сделать это. Я думаю об использовании Linq, но не знаю, как это сделать.

qinking126
источник
3
Enum.IsDefinedне хорошо?
leppie

Ответы:

155

Ты можешь использовать:

 Enum.IsDefined(typeof(Age), youragevariable)
AaronS
источник
IsDefined требует для проверки экземпляр Enum
Вячеслав Смитюх
9
Помните, что Enum.IsDefined()регистр учитывается! Так что это не «универсальное решение».
Чеширский кот,
7
Обычно рекомендуется не использовать IsDefined, поскольку Is использует отражение, что делает вызов IsDefined очень дорогостоящим с точки зрения производительности и ЦП. Вместо этого используйте TryParse. (изучено с сайта pluralsight.com)
Вэйхуэй Гуо
41

Вы можете использовать метод Enum.TryParse:

Age age;
if (Enum.TryParse<Age>("New_Born", out age))
{
    // You now have the value in age 
}
Джон Кернер
источник
5
Это доступно только в .NET 4
Гэри Рихтер
2
Проблема в том, что он вернет истину, если вы укажете ЛЮБОЕ целое число (я имею в виду вместо строки «New_Born»).
Romain Vincent
10

Вы можете использовать метод TryParse, который возвращает true в случае успеха:

Age age;

if(Enum.TryParse<Age>("myString", out age))
{
   //Here you can use age
}
Омар
источник
2

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

public static bool IsParsable<T>(this string value) where T : struct
{
    return Enum.TryParse<T>(value, true, out _);
}
Энди
источник
1

Вы должны использовать Enum.TryParse для достижения своей цели

Это пример:

[Flags]
private enum TestEnum
{
    Value1 = 1,
    Value2 = 2
}

static void Main(string[] args)
{
    var enumName = "Value1";
    TestEnum enumValue;

    if (!TestEnum.TryParse(enumName, out enumValue))
    {
        throw new Exception("Wrong enum value");
    }

    // enumValue contains parsed value
}
Вячеслав Смитюх
источник
1

Я знаю, что это старый поток, но здесь немного другой подход, использующий атрибуты в Enumerates, а затем вспомогательный класс для поиска соответствующего перечисления.

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

public enum Age
{
    [Metadata("Value", "New_Born")]
    [Metadata("Value", "NewBorn")]
    New_Born = 1,
    [Metadata("Value", "Toddler")]
    Toddler = 2,
    [Metadata("Value", "Preschool")]
    Preschool = 4,
    [Metadata("Value", "Kindergarten")]
    Kindergarten = 8
}

С моим вспомогательным классом, подобным этому

public static class MetadataHelper
{
    public static string GetFirstValueFromMetaDataAttribute<T>(this T value, string metaDataDescription)
    {
        return GetValueFromMetaDataAttribute(value, metaDataDescription).FirstOrDefault();
    }

    private static IEnumerable<string> GetValueFromMetaDataAttribute<T>(T value, string metaDataDescription)
    {
        var attribs =
            value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof (MetadataAttribute), true);
        return attribs.Any()
            ? (from p in (MetadataAttribute[]) attribs
                where p.Description.ToLower() == metaDataDescription.ToLower()
                select p.MetaData).ToList()
            : new List<string>();
    }

    public static List<T> GetEnumeratesByMetaData<T>(string metadataDescription, string value)
    {
        return
            typeof (T).GetEnumValues().Cast<T>().Where(
                enumerate =>
                    GetValueFromMetaDataAttribute(enumerate, metadataDescription).Any(
                        p => p.ToLower() == value.ToLower())).ToList();
    }

    public static List<T> GetNotEnumeratesByMetaData<T>(string metadataDescription, string value)
    {
        return
            typeof (T).GetEnumValues().Cast<T>().Where(
                enumerate =>
                    GetValueFromMetaDataAttribute(enumerate, metadataDescription).All(
                        p => p.ToLower() != value.ToLower())).ToList();
    }

}

тогда вы можете сделать что-то вроде

var enumerates = MetadataHelper.GetEnumeratesByMetaData<Age>("Value", "New_Born");

И для полноты картины вот атрибут:

 [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public class MetadataAttribute : Attribute
{
    public MetadataAttribute(string description, string metaData = "")
    {
        Description = description;
        MetaData = metaData;
    }

    public string Description { get; set; }
    public string MetaData { get; set; }
}
Jwsadler
источник
0

Чтобы разобрать возраст:

Age age;
if (Enum.TryParse(typeof(Age), "New_Born", out age))
  MessageBox.Show("Defined");  // Defined for "New_Born, 1, 4 , 8, 12"

Чтобы узнать, определено ли оно:

if (Enum.IsDefined(typeof(Age), "New_Born"))
   MessageBox.Show("Defined");

В зависимости от того, как вы планируете использовать Ageперечисление, флаги могут быть неправильными. Как вы, наверное, знаете, [Flags]означает, что вы хотите разрешить несколько значений (как в битовой маске). IsDefinedвернет false, Age.Toddler | Age.Preschoolпоскольку он имеет несколько значений.

агент-j
источник
2
Следует использовать TryParse, поскольку это непроверенный ввод.
Servy
1
MessageBox не имеет смысла в веб-среде.
Servy