2009-11-29 27 views
5

¿Es posible restringir un método genérico para aceptar solo tipos específicos de estructura?C# Genéricos, Restringir a estructuras específicas

Esto está bien que creen:

string Add<T>(object value, T expiration) where T : struct; 

pero esto no es lo que parece:

string Add<T>(object value, T expiration) where T : Struct1, Struct2; 

Nota: las estructuras que desear limitarla a DateTime son o TimeSpan y por lo tanto tengo sin control sobre ellos.

Gracias

Respuesta

7

No, ya que una estructura está sellada (no puede crear una subclase de un ValueType).

En su lugar, considerar la posibilidad de sus estructuras implementar una interfaz, y luego usar eso como una restricción, así:

string Add<T>(object value, T expiration) where T : struct, IMyInterface

+0

Estoy de acuerdo en que esto se debe lograr con las interfaces. ¡Este es uno de los propósitos de una interfaz! – Henri

+0

Gracias por su respuesta. ¿Puede explicar la importancia de no poder clasificar el tipo? Restringir el parámetro a estructuras (tipos de valores) parece posible y contradictorio con su afirmación. Las estructuras a las que deseo restringirme son DateTime o TimeSpan, por lo que envolverlas en una interfaz parecería ser la única solución (o dejar un genericised). – Ben

+2

No puede imponer una nueva interfaz en una estructura que no controla ('DateTime',' TimeSpan', etc.), entonces no: no puede hacer esto. –

-3

Creo que ambos no están bien, una estructura no es una restricción válida. Un tipo utilizado como restricción debe ser de interfaz, no sellado o un parámetro de tipo

+1

http://msdn.microsoft.com/en-us/library/d5x73970.aspx indica que el primero es correcto – Ben

+0

De hecho, existen otras restricciones más allá de los tipos: "new()" "struct" o "class". –

5

espero una sobrecarga es su mejor opción aquí:

string Add(object value, MyStruct1 expiration) {...} 
string Add(object value, MyStruct2 expiration) {...} 

Esto es aún más apropiado ya que no puede subclasificar una estructura, por lo tanto, el solo viable T en su ejemplo seríaMyStruct1 y MyStruct2 - también puede tener métodos específicos, entonces.

Re restringir genéricos a múltiples tipos citados; en realidad no, e incluso si existiera, el nombre "Agregar" sugiere que desea utilizar el soporte del operador, que también no está en C# (3.0).

Sin embargo, en C# 4.0, dynamic podría ser una opción aquí - esto actúa como una forma optimizada de pato-tipado; no obtendría soporte del compilador (validación, etc.), pero debería funcionar. Se podría emitir a dynamicdentro el método:

string Add<T>(object value, T expiration) where T : struct { 
    dynamic valueDyn = value; 
    valueDyn += expiration; // or similar 
    // more code 
} 

Otra opción (en .NET 3.5) es utilizar el Operator support en MiscUtil, utilizando Operator.Add o Operator.AddAlternative.

7

El propósito de los genéricos es hacer que los métodos y tipos que son genéricos, de ahí el nombre. Si solo tiene dos posibles argumentos de tipo, solo escriba dos métodos.

Recuerde también que los genéricos C# no son plantillas C++. Cuando llame a un método en un parámetro de tipo, por ejemplo, esa llamada a un método será , el mismo método de llamada para cada construcción del parámetro de tipo. Es generic. No es una plantilla donde el compilador compila el código dos, tres, mil veces, uno para cada argumento de tipo, y resuelve para cada uno cuál es la llamada al método.

Así que incluso si podría restringir su argumento tipo a dos tipos, ¿de qué serviría eso? Todo lo que podía invocar sobre ellos era los métodos que tenían en común a través de su clase base, Object. En cuyo caso, tiene un método genérico que funciona en todos los objetos, entonces, ¿por qué restringirlo a dos tipos?

+0

Podría usar 'void Foo (T x) donde T: I' en lugar de' void Foo (I x) 'ayuda a evitar el boxeo de' x' cuando ' T' es un tipo de valor por valor? [Aquí hay una pregunta relacionada] (http://stackoverflow.com/q/31457682/335858). – dasblinkenlight