65 votos

Alguien sabe una buena solución para la falta de una limitación genérica de enumeración?

Lo que quiero hacer es algo como esto: Tengo enumeraciones con valores marcados combinados.

 public static class EnumExtension
{
    public static bool IsSet<T>( this T input, T matchTo ) 
        where T:enum //the constraint I want that doesn't exist in C#3
    {    
    	return (input & matchTo) != 0;
    }
}
 

Así que lo que podía hacer:

 MyEnum tester = MyEnum.FlagA | MyEnum.FlagB

if( tester.IsSet( MyEnum.FlagA ) )
    //act on flag a
 

Desafortunadamente C # 's genérico donde las limitaciones no tienen restricción de enumeración, única clase y estructura. C # no ve enumeraciones como estructuras (a pesar de que son tipos de valor), así que no puede agregar tipos de extensión como este.

Alguien sabe alguna solución?

41voto

Jon Skeet Puntos 692016

EDIT: Esto es ahora vivo en la versión 0.0.0.2 de UnconstrainedMelody.

(Como se solicita en mi blog acerca de la enumeración de restricciones. He incluido los datos básicos a continuación para el bien de una respuesta independiente.)

La mejor solución es esperar a que me lo incluyen en UnconstrainedMelody1. Esta es una biblioteca que lleva de código de C# con "falso" restricciones tales como

where T : struct, IEnumConstraint

y la convierte en

where T : struct, System.Enum

a través de un postbuild paso.

No debería ser demasiado difícil escribir IsSet... a pesar de catering para ambos Int64-y basadas UInt64-base de indicadores podría ser la parte difícil. (Me huele a algunos métodos auxiliares procedentes, básicamente, lo que me permite tratar cualquier banderas enum como si hubiera un tipo de base de UInt64.)

¿Qué desea usted que el comportamiento se si se llama

tester.IsSet(MyFlags.A | MyFlags.C)

? Debe comprobar que todos los indicadores especificados, se establecen? Que sería de mi expectativa.

Voy a tratar de hacer esto en el camino a casa esta noche... estoy esperando a tener un rápido relámpago útil enumeración de los métodos para obtener de la biblioteca a un estándar utilizable rápidamente, y luego relajarse un poco.

EDIT: no estoy seguro acerca de IsSet como un nombre, por cierto. Opciones:

  • Incluye
  • Contiene
  • HasFlag (o HasFlags)
  • IsSet (es una opción)

Pensamientos de bienvenida. Estoy seguro de que va a ser un rato antes de que nada de lo establecido en la piedra de todos modos...


1 o presentarlo como un parche, por supuesto...

16voto

Ronnie Puntos 3742

Darren, que funcionaría si los tipos eran enumeraciones específicas - para enumeraciones generales para trabajar hay que echarlos a enteros (o más probable uint) que hacer el booleano matemáticas:

 public static bool IsSet( this Enum input, Enum matchTo )
{
    return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0;
}
 

6voto

SLaks Puntos 391154

En realidad, es posible, con un truco feo. Sin embargo, no puede ser utilizado para los métodos de extensión.

 public abstract class Enums<Temp> where Temp : class {
    public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
    	return (TEnum)Enum.Parse(typeof(TEnum), name); 
    }
}
public abstract class Enums : Enums<Enum> { }

Enums.IsSet<DateTimeKind>("Local")
 

Si quieres, puedes darle Enums<Temp> un constructor privado y una clase abstracta anidada pública heredada con Temp como Enum , para evitar que las versiones heredadas de los no enumeraciones .

5voto

Simon Puntos 11945

Esto se puede conseguir usando IL Weaving y ExtraConstraints

Le permite escribir el código

 public class Sample
{
    public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
    {        
    }
    public void MethodWithEnumConstraint<[EnumConstraint] T>()
    {
    }
}
 

Lo que se compila

 public class Sample
{
    public void MethodWithDelegateConstraint<T>() where T: Delegate
    {
    }

    public void MethodWithEnumConstraint<T>() where T: struct, Enum
    {
    }
}
 

3voto

thecoop Puntos 23695

La manera de hacerlo es poner un struct restricción, a continuación, comprobar que T es una enumeración en tiempo de ejecución. Esto no elimina el problema por completo, pero sí reducirla un poco

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X