як перевірити, чи є значення рядка в списку Enum?


91

У своєму рядку запиту я маю змінну віку ?age=New_Born.

Чи є спосіб перевірити, чи є це рядкове значення New_Bornу моєму списку Enum

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

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


2
Enum.IsDefinedне добре?
леппі

Відповіді:


153

Ви можете використовувати:

 Enum.IsDefined(typeof(Age), youragevariable)

IsDefined вимагає перевірки екземпляру Enum
В’ячеслав Смітюх

9
Пам’ятайте, що Enum.IsDefined()це чутливо до регістру! Тож це не «універсальне рішення».
Чеширський кіт

6
Зазвичай рекомендується не використовувати IsDefined, оскільки Is використовує відображення, роблячи виклик IsDefined дуже дорогим викликом з точки зору продуктивності та процесора. Замість цього використовуйте TryParse. (дізнався з pluralsight.com)
Вейхуей Го

40

Ви можете використовувати метод 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").
Ромен Вінсент

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

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оскільки має кілька значень.


2
Слід використовувати TryParse, оскільки це неперевірене введення.
Серві

1
MessageBox насправді не має сенсу у веб-середовищі.
Серві
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.