En genéricos de C #, podemos declarar una restricción para que un parámetro de tipo T
tenga un constructor predeterminado, diciendo where T : new()
. Sin embargo, ningún otro tipo de restricciones como esta son válidas, new(string)
por ejemplo, etc.
Desde una perspectiva de diseño y / o implementación de lenguaje, ¿cuál es la razón de esto?
¿Hay algo en la forma en que funcionan los constructores o en la forma en que se implementa el sistema de tipos que prohíbe esto (o al menos lo hace más difícil)? Si es así, ¿qué es? Recuerdo haber leído en algún lugar que default(T)
realmente compila new T()
para T : struct
. ¿Está relacionado con esto, tal vez?
¿O es simplemente una decisión de diseño tomada para evitar complicar demasiado el lenguaje?
c#
language-design
generics
Theodoros Chatzigiannakis
fuente
fuente
new(string)
no es una restricción de constructor predeterminada. Su pregunta equivale a decir "¿Por qué no hay restricciones que requieran firmas de constructor específicas?" Muy probablemente porque tal restricción no sería particularmente útil.Respuestas:
Para una respuesta autorizada, lo remitiría a la respuesta de Eric Lippert a esa pregunta en StackOverflow hace unos años, un fragmento del cual se cita brevemente a continuación.
fuente
La descomposición (según la sugerencia de Robert Harvey) produjo lo siguiente, para cualquier persona interesada. Este método:
Aparentemente, cuando se compila, se convierte en esto:
T
es un tipo de valor,new()
convierte endefault(T)
.T
es un tipo de referencia,new()
funciona utilizando la reflexión.Activator.CreateInstance()
Llamadas internasRuntimeType.CreateInstanceDefaultCtor()
.Así que ahí está: internamente, los constructores predeterminados son realmente especiales para C # en relación con el CLR. Dar a otros constructores el mismo tratamiento hubiera sido costoso, incluso si hay algunos casos de uso válidos para restricciones más complicadas en genéricos.
fuente
default(T)
tipos de valor?t
variable (que podría reemplazarse porreturn
declaraciones anidadas ).