2009-12-06 8 views
43
  • ¿Por qué no puedo usar una restricción de where T : System.ValueType?
  • ¿Por qué Microsoft evita que este tipo sea una restricción?

Ejemplo:¿Por qué no puedo usar System.ValueType como una restricción de genéricos?

Por qué no puedo hacer lo siguiente?

// Defined in a .Net class 
public void bar<T>(T a) where T : ValueType {...} 

// Defined in my class 
public void foo<T>(T a) where T : ValueType 
{ bar<T>(a); } 

¿Cuál es la diferencia entre utilizar struct sobre ValueType?

// Defined in my class 
public void foo<T>(T a) where T : struct 
{ bar<T>(a); } 

Respuesta

60

Hay dos diferencias entre el uso

where T : struct 

y

where T : ValueType 
  • el último sería permitir T para ser ValueType misma, que es un tipo de referencia.
  • este último también permitiría T a ser un tipo de valor anulable

La primera de estas diferencias casi nunca es lo que quiere. El segundo podría ocasionalmente ser útil; Nullable<T> es un poco extraño ya que no satisface la restricción where T : struct ni where T : class.

Más útil sería la restricción

where T : struct, System.Enum 

lo cual está prohibido por C# por ninguna buena razón por la que puedo decir. Consulte my blog post y Unconstrained Melody project para obtener más información al respecto.

+6

Tengo que decir que siempre me he preguntado por qué no podemos limitarlos como 'donde T: struct, System.Enum'. ¡Sería * tan útil * a veces! –

+0

En realidad, puede hacer 'donde T: Enum' y' donde T: ValueType' en F # (usando su sintaxis 'cuando 'T:> Enum') y de hecho, funciona como Jon espera que funcione. Para el enum-type-constraint, funciona con enumeraciones genéricas como 'enum ' y 'System.Enum', y prohíbe correctamente los tipos de valores como 'byte' o' int'. Para responder la pregunta de Jon al "por qué" es tan difícil agregar a C#, vea esta discusión de Roslyn: https://github.com/dotnet/roslyn/issues/262 – Abel

12

ValueType no es la clase base de tipos de valores, simplemente es un contenedor para el valor cuando está encuadrado. Dado que es una clase de contenedor y no está en ningún tipo de jerarquía para los tipos reales que desea utilizar, no es útil como restricción genérica.

+0

No del todo, no del todo. En IL, puede ver claramente la declaración de cualquier tipo de valor que tenga 'extends System.ValueType', lo que lo convierte efectivamente en la clase base. Creo que su papel principal es como marcador para distinguir entre una clase y un tipo de valor, pero no estoy seguro. – Abel

6

El uso de struct como una restricción genérica es funcionalmente equivalente a una restricción de "ValueType". En .NET, a struct is a value type.

+0

Una estructura es un 'ValueType', sí, pero no todos los tipos de valores son una estructura, por ejemplo,' ValueType' en sí no es una estructura, ni son tipos de valores que aceptan valores. – Abel

Cuestiones relacionadas