jak sprawdzić, czy wartość ciągu znajduje się na liście wyliczeń?


92

W moim ciągu zapytania mam zmienną wieku ?age=New_Born.

Czy istnieje sposób, aby sprawdzić, czy ta wartość ciągu New_Bornznajduje się na mojej liście Enum

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

Mógłbym teraz użyć instrukcji if, ale jeśli moja lista Enum się powiększy. Chcę znaleźć lepszy sposób, aby to zrobić. Zastanawiam się nad użyciem Linq, tylko nie wiem, jak to zrobić.


3
Enum.IsDefinednie w porządku?
leppie

Odpowiedzi:


155

Możesz użyć:

 Enum.IsDefined(typeof(Age), youragevariable)

IsDefined wymaga do sprawdzenia instancji Enum
Viacheslav Smityukh

9
Pamiętaj, że Enum.IsDefined()rozróżniana jest wielkość liter! Nie jest to więc „uniwersalne rozwiązanie”.
Cheshire Cat

7
Zwykle nie zaleca się używania funkcji IsDefined, ponieważ używa ona odbicia, przez co wywołanie IsDefined jest bardzo kosztowne pod względem wydajności i procesora. Zamiast tego użyj TryParse. (informacje z pluralsight.com)
Weihui Guo

41

Możesz użyć metody Enum.TryParse:

Age age;
if (Enum.TryParse<Age>("New_Born", out age))
{
    // You now have the value in age 
}

5
To jest dostępne tylko od .NET 4
Gary Richter,

2
Problem z tym polega na tym, że zwróci wartość true, jeśli podasz JAKĄKOLWIEK liczbę całkowitą (zamiast ciągu „New_Born”, mam na myśli).
Romain Vincent

11

Możesz użyć metody TryParse , która zwraca wartość true, jeśli się powiedzie:

Age age;

if(Enum.TryParse<Age>("myString", out age))
{
   //Here you can use age
}

2

Mam poręczną metodę rozszerzającą, która używa TryParse, ponieważ IsDefined rozróżnia wielkość liter.

public static bool IsParsable<T>(this string value) where T : struct
{
    return Enum.TryParse<T>(value, true, out _);
}

1

Aby osiągnąć swój cel, powinieneś użyć Enum.TryParse

Oto przykład:

[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

Wiem, że jest to stary wątek, ale tutaj jest nieco inne podejście wykorzystujące atrybuty w wyliczeniach, a następnie klasa pomocnicza, aby znaleźć wyliczenie, które pasuje.

W ten sposób można mieć wiele mapowań na jednym wyliczeniu.

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
}

Z taką klasą pomocników

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

}

możesz wtedy zrobić coś takiego

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

A dla kompletności jest tutaj atrybut:

 [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

Aby przeanalizować wiek:

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

Aby sprawdzić, czy jest zdefiniowane:

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

W zależności od tego, jak planujesz używać Agewyliczenia, flagi mogą nie być właściwe. Jak zapewne wiesz, [Flags]oznacza, że ​​chcesz zezwolić na wiele wartości (jak w masce bitowej). IsDefinedzwróci false, Age.Toddler | Age.Preschoolponieważ ma wiele wartości.


2
Powinien używać TryParse, ponieważ jest to niezweryfikowane dane wejściowe.
Servy

1
MessageBox nie ma sensu w środowisku sieciowym.
Servy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.