2011-03-03 8 views
12

Creo que hay gente que puede ser capaz de responder a esto, esta es una pregunta por curiosidad:Más curiosidades que realmente importante: ¿Por qué hay nuevo() restricción en Activator.CreateInstance <T>()?

El método genérico CreateInstance de System.Activator, introducido en .NET v2 no tiene restricciones de tipo genérico en el argumento, pero requiere un constructor predeterminado en el tipo activado; de lo contrario, se lanza un MissingMethodException. Me parece obvio que este método debe tener una restricción de tipo como

Activator.CreateInstance<T>() where T : new() { 
    ... 
} 

Sólo una omisión o alguna anécdota que acechan aquí?

actualización

Como se ha señalado, el compilador no le permiten escribir

private T Create<T>() where T : struct, new() 
error CS0451: The 'new()' constraint cannot be used with the 'struct' constraint 

Sin embargo, ver los comentarios una estructura se puede utilizar como argumento de tipo a un método genérico que especifica una nueva () restricción Bajo esta circunstancia, la respuesta dada parece la única razón válida para no restringir el método ...

¡Gracias por mirar esto!

+0

1 pregunta muy interesante. No puedo pensar en una razón por la que no debería estar allí, ¡así que también tengo curiosidad por saber por qué! –

+0

En cuanto a su actualización, porque es redundante; todos los tipos de valores tienen un constructor predeterminado que inicializa todos los valores por defecto (es lo que obtienes cuando llamas 'default (T)'. –

+0

Todas las estructuras tienen ctors predeterminadas en C#. – Linkgoron

Respuesta

7

Podría estar equivocado, pero el beneficio principal que veo es que le permite hacer algo como esto:

// Simple illustration only, not claiming this is awesome code! 
class Cache<T> 
{ 
    private T _instance; 

    public T Get() 
    { 
     if (_instance == null) 
     { 
      _instance = Create(); 
     } 

     return _instance; 
    } 

    protected virtual T Create() 
    { 
     return Activator.CreateInstance<T>(); 
    } 
} 

Tenga en cuenta que si Activator.CreateInstance<T> tenían una restricción where T : new(), entonces la clase Cache<T> anterior sería también necesita esa restricción, que sería demasiado restrictivo ya que Create es un método virtual y alguna clase derivada podría querer usar un medio diferente de creación de instancias, como llamar al constructor interno de un tipo o usar un método de generador estático.

+0

1. eso es un punto excelente. Mientras que usted está asumiendo un cierto riesgo (es posible que ' t' no tiene un constructor por defecto aquí, obviamente), esto parece un caso perfectamente válida. –

+0

Sí, suena razonable – flq

+0

Por cierto, parece que 'Sy stem.Runtime.CompilerServices.ConditionalWeakTable' hace esto mismo. –

Cuestiones relacionadas