¿Cómo verificar si el valor de la cadena está en la lista Enum?

91

En mi cadena de consulta, tengo una variable de edad ?age=New_Born.

¿Hay alguna manera de verificar si este valor de cadena New_Bornestá en mi lista Enum?

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

Podría usar la declaración if por ahora, pero si mi lista Enum aumenta. Quiero encontrar una mejor manera de hacerlo. Estoy pensando en usar Linq, pero no estoy seguro de cómo hacerlo.

qinking126
fuente
2
Enum.IsDefined¿no está bien?
leppie

Respuestas:

153

Puedes usar:

 Enum.IsDefined(typeof(Age), youragevariable)
AaronS
fuente
IsDefined requiere una instancia de Enum para verificar
Viacheslav Smityukh
9
¡Recuerde que distingue entre Enum.IsDefined()mayúsculas y minúsculas! Entonces esa no es una "solución universal".
Gato de Cheshire
6
Normalmente se recomienda que no se utilice IsDefined, porque Is utiliza la reflexión, lo que hace que una llamada a IsDefined sea una llamada muy cara en términos de rendimiento y CPU. Utilice TryParse en su lugar. (aprendido de pluralsight.com)
Weihui Guo
40

Puede utilizar el método Enum.TryParse:

Age age;
if (Enum.TryParse<Age>("New_Born", out age))
{
    // You now have the value in age 
}
John Koerner
fuente
5
Esto solo está disponible a partir de .NET 4
Gary Richter
2
El problema con esto es que devolverá verdadero si proporciona CUALQUIER entero (en lugar de su cadena "New_Born", quiero decir).
Romain Vincent
10

Puede usar el método TryParse que devuelve verdadero si tiene éxito:

Age age;

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

Tengo un método de extensión útil que usa TryParse, ya que IsDefined distingue entre mayúsculas y minúsculas.

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

Deberías usar Enum.TryParse para lograr tu objetivo

Este es un ejemplo:

[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
fuente
1

Sé que este es un hilo antiguo, pero aquí hay un enfoque ligeramente diferente que usa atributos en Enumerates y luego una clase auxiliar para encontrar la enumeración que coincide.

De esta manera, podría tener múltiples asignaciones en una sola enumeración.

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 mi clase de ayudante como esta

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

}

entonces puedes hacer algo como

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

Y para completar, aquí está el 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
fuente
0

Para analizar la edad:

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

Para ver si está definido:

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

Dependiendo de cómo planee usar la Ageenumeración, las banderas pueden no ser lo correcto. Como probablemente sepa, [Flags]indica que desea permitir múltiples valores (como en una máscara de bits). IsDefineddevolverá falso Age.Toddler | Age.Preschoolporque tiene varios valores.

agente-j
fuente
2
Debería usar TryParse ya que es una entrada no verificada.
Servicio
1
MessageBox realmente no tiene sentido en un entorno web.
Servicio