como verificar se o valor da string está na lista Enum?

91

Em minha string de consulta, tenho uma variável de idade ?age=New_Born.

Existe uma maneira de verificar se este valor de string New_Bornestá na minha lista Enum

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

Eu poderia usar a instrução if agora, mas se minha lista Enum ficar maior. Eu quero encontrar uma maneira melhor de fazer isso. Estou pensando em usar o Linq, mas não tenho certeza de como fazê-lo.

qinking126
fonte
2
Enum.IsDefinednão está tudo bem?
leppie

Respostas:

152

Você pode usar:

 Enum.IsDefined(typeof(Age), youragevariable)
AaronS
fonte
IsDefined requer instância Enum para verificação
Viacheslav Smityukh
9
Lembre-se de que diferencia Enum.IsDefined()maiúsculas de minúsculas! Portanto, essa não é uma "solução universal".
Cheshire Cat
6
Normalmente é recomendado que IsDefined não seja usado, pois Is usa reflexão, fazendo uma chamada para IsDefined uma chamada muito cara em termos de desempenho e CPU. Em vez disso, use TryParse. (aprendido em pluralsight.com)
Weihui Guo
40

Você pode usar o método Enum.ExperimenteParse:

Age age;
if (Enum.TryParse<Age>("New_Born", out age))
{
    // You now have the value in age 
}
John Koerner
fonte
5
Disponível apenas a partir do .NET 4
Gary Richter
2
O problema com isso é que ele retornará verdadeiro se você fornecer QUALQUER inteiro (em vez de sua string "New_Born", quero dizer).
Romain Vincent
10

Você pode usar o método TryParse que retorna verdadeiro se for bem-sucedido:

Age age;

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

Eu tenho um método de extensão útil que usa TryParse, pois IsDefined faz distinção entre maiúsculas e minúsculas.

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

Você deve usar Enum.ExperimenteParse para atingir seu objetivo

Este é um exemplo:

[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
}
Viacheslav Smityukh
fonte
1

Eu sei que este é um thread antigo, mas aqui está uma abordagem ligeiramente diferente usando atributos em Enumerates e, em seguida, uma classe auxiliar para encontrar o enumerado que corresponda.

Dessa forma, você pode ter vários mapeamentos em um único enumerado.

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
}

Com minha aula de ajudante assim

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

}

você pode então fazer algo como

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

E para completar aqui está o atributo:

 [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
fonte
0

Para analisar a idade:

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

Para ver se está definido:

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

Dependendo de como você planeja usar o Ageenum, os sinalizadores podem não ser a coisa certa. Como você provavelmente sabe, [Flags]indica que deseja permitir vários valores (como em uma máscara de bits). IsDefinedretornará falso para Age.Toddler | Age.Preschoolporque tem vários valores.

agente-j
fonte
2
Deve usar TryParse, pois é uma entrada não verificada.
Servy
1
MessageBox realmente não faz sentido em um ambiente da web.
Servy