2009-10-30 14 views
26

¿Hay alguna diferencia entre seguir dos formas de crear un objeto.Activator.CreateInstance <T> Vs new

Student s1 = Activator.CreateInstance<Student>(); 
Student s1 = new Student(); 
  • ¿Hay alguna diferencia en la forma en que se llama al constructor o al inicializar la memoria?
  • Según entiendo, el primer método parece completamente redundante. Si el programador conoce el tipo de datos durante el tiempo de diseño, usará el segundo método.
+0

Relacionados: http://stackoverflow.com/questions/6582259/fast-creation-of-objects-instead-of-activator-createinstancetype, http://stackoverflow.com/questions/6069661/does-system-activator -createinstancet-have-performance-issues-big-enough-to-di – nawfal

Respuesta

12

Esta sobrecarga del método "Activator.CreateInstance" se utiliza por los compiladores para implementar la creación de instancias de tipos especificados por el uso de parámetros de tipo genéricos.

Digamos que tiene el siguiente método:

public static T Factory<T>() where T: new() 
{ 
    return new T(); 
} 

el compilador convertir el "retorno nueva T();" para llamar a "CreateInstance".

En general, no hay ningún uso para CreateInstance en el código de la aplicación, porque el tipo debe conocerse en tiempo de compilación. Si el tipo se conoce en tiempo de compilación, se puede usar la sintaxis de instanciación normal (nuevo operador en C#, Nuevo en Visual Basic, gnenew en C++).

Más información: http://msdn.microsoft.com/en-us/library/0hcyx2kd.aspx

+10

Es muy común que un tipo sea desconocido en tiempo de compilación. Es muy útil al separar el contrato (interfaz) y la implementación. – Thorarin

+0

¡Sería muy difícil escribir el código de deserialización sin 'CreateInstance'! – Gabe

+0

Llamaría al último párrafo como equivocado. Es bastante común tener un nombre de tipo en una configuración y la necesidad de crear una instancia. Supongo que se refiere específicamente a la sobrecarga genérica (utilizada en la pregunta) que requeriría el tipo concreto en tiempo de compilación. –

3

No, Activator.CreateInstance<T> simplemente llama al constructor por defecto debajo de las cubiertas. La única diferencia entre sus ejemplos es una llamada de método extra al CreateInstance<T>.

De Activator.CreateInstance<T>:

crea una instancia del tipo designado por el parámetro tipo genérico especificado, utilizando el constructor sin parámetros.

4

Llamar a nuevo es mejor en cuanto a rendimiento CreateInstance probablemente utiliza el reflejo que es lento.
Si conoce el tipo durante el tiempo de diseño, use nuevo, incluso si las dos llamadas fueron exactamente iguales (¡no lo son!) ¿Por qué complicar demasiado su código?

Use Activator.CreateInstance solo cuando no se conoce el tipo de T en el tiempo de diseño y necesita una resolución en tiempo de ejecución del tipo.

+0

sí, utiliza la reflexión y por lo tanto, 'nueva T()' debe ser preferida en lugar de 'Activator.CreateInstance ()' ([Fuente] (http : //typedescriptor.net/browse/members/246503-System.Activator.CreateInstance [T]())). – Shimmy

5

No llamaría al Activator.CreateInstance() redundante.

Si conoce el tipo, sí, simplemente usaría new. Sin embargo, en situaciones que requieren la carga dinámica de tipos desconocidos desde frameworks de plugins o donde el tipo es analizado desde una cadena (desde, por ejemplo, un archivo de configuración), es extremadamente útil.

Y para responder a la pregunta sobre la diferencia entre los dos, no, debajo del capó no hay diferencia real entre llamar new T() y Activator.CreateInstance<T>(), como ya ha sido señalado por Andrew Hare.

EDIT: No importa, me he confundido el genérica CreateInstance<T>() con la de otro modo más utilizado normalmente CreateInstance(Type type)

3

Una diferencia grande es que

Student s1 = new Student(); 

no se compilará si no hay un constructor por defecto en Student, mientras que

Student s1 = Activator.CreateInstance<Student>(); 

compilará incluso si Student hace no tener un constructor por defecto (Compilará y le permitirá ejecutar el programa, pero si no hay un constructor que coincida obtendrá una excepción, mientras que la llamada del constructor ni siquiera se compilará si el constructor no existe)

Igualmente, la llamada CreateInstance es un uso implícito de la clase, por lo que, por ejemplo, Resharper no sabrá que está instanciando, y podría decirle que la clase nunca se crea una instancia.

Como se ha mencionado en otras respuestas, la llamada CreateInstance también permite el uso de un parámetro de tipo genérico:

T s1 = Activator.CreateInstance<T>(); 

aunque probablemente sería mejor usar una restricción new tipo, ya que daría compilar -asegura de que realmente hay un constructor que se llamará.

Las sobrecargas Activator.CreateInstance(Type, ...) son mucho más útiles, sin embargo.

+0

¿Estás seguro? ¿A qué constructor llamaría, si no hay uno predeterminado? ¿Qué parámetros pasaría a ese constructor? –

+0

@ZarShardan Lanzaría una excepción. Mi punto era que todavía se compilará; es decir: obtendrá un error de tiempo de ejecución en lugar de un error del compilador. (los errores del compilador son preferibles) –

Cuestiones relacionadas