come verificare se il valore della stringa è nell'elenco Enum?


91

Nella mia stringa di query, ho una variabile di età ?age=New_Born.

C'è un modo per verificare se questo valore di stringa New_Bornè nel mio elenco Enum

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

Potrei usare l'istruzione if per ora, ma se il mio elenco Enum diventa più grande. Voglio trovare un modo migliore per farlo. Sto pensando di usare Linq, ma non sono sicuro di come farlo.


2
Enum.IsDefinednon bene?
leppie

Risposte:


153

Puoi usare:

 Enum.IsDefined(typeof(Age), youragevariable)

IsDefined richiede che l'istanza Enum controlli
Viacheslav Smityukh

9
Ricorda che Enum.IsDefined()fa distinzione tra maiuscole e minuscole! Quindi non è una "soluzione universale".
Gatto del Cheshire

6
Normalmente si consiglia di non utilizzare IsDefined, perché Is utilizza la reflection, rendendo una chiamata a IsDefined una chiamata molto costosa in termini di prestazioni e CPU. Utilizza invece TryParse. (appreso da pluralsight.com)
Weihui Guo

40

Puoi utilizzare il metodo Enum.TryParse:

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

5
Questo è disponibile solo a partire da .NET 4
Gary Richter

2
Il problema con questo è che restituirà vero se fornisci QUALSIASI numero intero (invece della tua stringa "New_Born", intendo).
Romain Vincent

10

Puoi utilizzare il metodo TryParse che restituisce true se ha esito positivo:

Age age;

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

2

Ho un pratico metodo di estensione che utilizza TryParse, poiché IsDefined fa distinzione tra maiuscole e minuscole.

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

1

Dovresti usare Enum.TryParse per raggiungere il tuo obiettivo

Questo è un esempio:

[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

So che questo è un vecchio thread, ma ecco un approccio leggermente diverso che utilizza attributi su Enumerates e quindi una classe helper per trovare l'enumerazione che corrisponde.

In questo modo potresti avere più mappature su un singolo enumerato.

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
}

Con la mia classe di aiuto come questa

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

}

puoi quindi fare qualcosa di simile

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

E per completezza ecco l'attributo:

 [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

Per analizzare l'età:

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

Per vedere se è definito:

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

A seconda di come prevedi di usare l' Ageenumerazione, i flag potrebbero non essere la cosa giusta. Come probabilmente saprai, [Flags]indica che desideri consentire più valori (come in una maschera di bit). IsDefinedrestituirà false per Age.Toddler | Age.Preschoolperché ha più valori.


2
Dovrebbe usare TryParse poiché è un input non verificato.
Servy

1
MessageBox non ha davvero senso in un ambiente web.
Servy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.