Pregunta

En vs2008, ¿es posible escribir métodos de extensión que se apliquen a cualquier enumeración?

Sé que puedes escribir métodos de extensión contra una enumeración específica, pero quiero poder hacer cada enumeración usando un único método de extensión. ¿Es esto posible?

¿Fue útil?

Solución

Sí, solo codifique contra el tipo base Enum , por ejemplo

public static void Something(this Enum e)
{
    // code here
}

La desventaja es que probablemente terminarás haciendo cosas bastante desagradables como encontrar el tipo base real usando Enum.GetUnderlyingType , lanzando y bajando diferentes ramas dependiendo de cuál sea el tipo base de la enumeración, pero puede encontrar algo bueno utiliza para ello (por ejemplo, tenemos los métodos IsOneOf y IsCombinationOf que se aplican a todas las enumeraciones).

PD: Recuerde al escribir el método que, aunque mal aconsejado, puede usar float y double como los tipos básicos para enumeraciones, por lo que necesitará algunos casos especiales tanto para aquellos como para los valores sin signo.

Otros consejos

Sí, puedes. El tipo de extensión de destino es del tipo Enum . En C #, esto se haría como:

public static void EnumExtension(this Enum e)
{
}

o como esto en VB:

<Extension()> _
Public Sub EnumExtension(ByVal s As Enum)
End Sub

FYI Aquí hay un gran ejemplo de un método de extensión Enum que he podido usar. Implementa una función TryParse () sin distinción entre mayúsculas y minúsculas para las enumeraciones:

public static class ExtensionMethods
{
    public static bool TryParse<T>(this Enum theEnum, string strType, 
        out T result)
    {
        string strTypeFixed = strType.Replace(' ', '_');
        if (Enum.IsDefined(typeof(T), strTypeFixed))
        {
            result = (T)Enum.Parse(typeof(T), strTypeFixed, true);
            return true;
        }
        else
        {
            foreach (string value in Enum.GetNames(typeof(T)))
            {
                if (value.Equals(strTypeFixed, 
                    StringComparison.OrdinalIgnoreCase))
                {
                    result = (T)Enum.Parse(typeof(T), value);
                    return true;
                }
            }
            result = default(T);
            return false;
        }
    }
}

Lo usarías de la siguiente manera:

public enum TestEnum
{
    A,
    B,
    C
}

public void TestMethod(string StringOfEnum)
{
    TestEnum myEnum;
    myEnum.TryParse(StringOfEnum, out myEnum);
}

Estos son los dos sitios que visité para ayudar a crear este código:

Case Insensitive TryParse para Enums

Métodos de extensión para Enums

Aquí hay otro ejemplo: también es mejor en mi humilde opinión que tener que crear e inicializar una variable temporal.

public static class ExtensionMethods 
{
    public static void ForEach(this Enum enumType, Action<Enum> action)
    {
        foreach (var type in Enum.GetValues(enumType.GetType()))
        {
            action((Enum)type);
        }
    }
}

public enum TestEnum { A,B,C } 
public void TestMethod() 
{
    default(TestEnum).ForEach(Console.WriteLine); 
} 

También puede implementar el método de conversión de la siguiente manera:

public static class Extensions
{
    public static ConvertType Convert<ConvertType>(this Enum e)
    {
        object o = null;
        Type type = typeof(ConvertType);

        if (type == typeof(int))
        {
            o = Convert.ToInt32(e);
        }
        else if (type == typeof(long))
        {
            o = Convert.ToInt64(e);
        }
        else if (type == typeof(short))
        {
            o = Convert.ToInt16(e);
        }
        else
        {
            o = Convert.ToString(e);
        }

        return (ConvertType)o;
    }
}

Aquí hay un ejemplo de uso:

int a = MyEnum.A.Convert<int>();

A veces es necesario convertir de una enumeración a otra, según el nombre o el valor de la enumeración. Así es como se puede hacer bien con los métodos de extensión:

enum Enum1 { One = 1, Two = 2, Three = 3 };
enum Enum2 { Due = 2, Uno = 1 };
enum Enum3 { Two, One };

Enum2 e2 = Enum1.One.ConvertByValue<Enum2>();
Enum3 e3 = Enum1.One.ConvertByName<Enum3>();
Enum3 x2 = Enum1.Three.ConvertByValue<Enum3>();

public static class EnumConversionExtensions
{
    public static T ConvertByName<T>(this Enum value)
    {
        return (T)Enum.Parse(typeof(T), Enum.GetName(value.GetType(), value));
    }

    public static T ConvertByValue<T>(this Enum value)
    {
        return (T)((dynamic)((int)((object)value)));
    }
}

Otro ejemplo de cómo hacer la extensión Enum, pero esta vez devuelve el tipo de entrada enum.

public static IEnumerable<T> toElementsCollection<T>(this T value) where T : struct, IConvertible
    {
        if (typeof(T).IsEnum == false) throw new Exception("typeof(T).IsEnum == false");

        return Enum.GetValues(typeof(T)).Cast<T>();
    }

Ejemplo de uso:

public enum TestEnum { A,B,C };

TestEnum.A.toElementsCollection();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top