2011-06-30 13 views
109

Se puede ver lo que estoy tratando (pero no) que ver con el siguiente código:C# Crear nuevo T()

protected T GetObject() 
{ 
    return new T(); 
} 

Cualquier ayuda sería muy apreciada.

EDITAR:

El contexto era el siguiente. Estaba jugando con una clase de controlador personalizado para todos los controladores a partir de, con métodos estandarizados. Entonces, en contexto, necesitaba crear una nueva instancia del objeto del tipo de controlador. Así que al momento de escribir, era algo así como:

public class GenericController<T> : Controller 
{ 
    ... 

    protected T GetObject() 
    { 
     return (T)Activator.CreateInstance(ObjectType); 
    }   

    public ActionResult Create() 
    { 
     var obj = GetObject() 

     return View(obj); 
    } 

Así que decidí que la reflexión era más fácil aquí. Estoy de acuerdo en que, ciertamente dado el enunciado inicial de la pregunta, la respuesta más adecuada para marcar como correcta fue la que usa la nueva restricción(). Lo he arreglado.

+27

No, no veo lo que estamos tratando y de no hacerlo. Veo un fragmento de código que podría ser parte de un programa en funcionamiento, sin contexto, sin mensaje de error y sin explicación. –

+17

Aw, ¡Odio cuando se selecciona la respuesta incorrecta! –

+1

Agregue el contexto. – James

Respuesta

305

Tome un vistazo a new Constraint

public class MyClass<T> where T : new() 
{ 
    protected T GetObject() 
    { 
     return new T(); 
    } 
} 

T podría ser una clase que no tiene un constructor por defecto: en este caso new T() sería una declaración válida. La restricción new() dice que T debe tener un constructor predeterminado, lo que hace que new T() sea legal.

Se puede aplicar la misma restricción a un método genérico:

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

Si necesita pasar parámetros:

protected T GetObject(params object[] args) 
{ 
    return (T)Activator.CreateInstance(typeof(T), args); 
} 
+2

Gracias, amigo, estoy contento de haber aprendido esto hoy. Dado el contexto de mi método, opté por la solución de reflexión. ¡Aclamaciones! – Hanshan

+8

@nulliusinverba - hmm ... sería bueno si mostraras el contexto de tu método en la pregunta. –

+1

@nulliusinverba: no apareciste en la pregunta que necesitabas parámetros. –

27

Otra forma es utilizar la reflexión:

protected T GetObject<T>(Type[] signature, object[] args) 
{ 
    return (T)typeof(T).GetConstructor(signature).Invoke(args); 
} 
+0

Gracias, amigo - Fui con esta solución dado el contexto del método. – Hanshan

+21

Al igual que un FYI, esto puede escribirse alternativamente como Activator.CreateInstance (typeof (T), signature, args); ver http://msdn.microsoft.com/en-us/library/4b0ww1we.aspx para más detalles. –

+0

@Calgary Coder: ¿Cuál es el uso para una firma de tipo []? Simplemente puede llamar a CreateInstance con params directamente, sin especificar explícitamente la firma. En ambos casos, obtendría MissingMethodException si no existe un constructor que coincida. –

18

Solo para completar, la mejor solución aquí es a menudo requerir un argumento de función de fábrica:

T GetObject<T>(Func<T> factory) 
{ return factory(); } 

y llamarlo algo como esto:

string s = GetObject(() => "result"); 

Usted puede utilizar eso para exigir o hacer uso de los parámetros disponibles, si es necesario.

12

El new constraint está muy bien, pero si necesita T es un tipo de valor demasiado, utilice esto:

protected T GetObject() { 
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) { 
     return default(T); 
    } else { 
     return (T)Activator.CreateInstance(typeof(T)); 
    } 
} 
7

Dado que esta es etiquetada C# 4. Con el marco sourece abierto ImpromptuIntereface usará el dlr para llamar al constructor, es significativamente más rápido que el Activador cuando su constructor tiene argumentos, y es insignificantemente más lento cuando no lo hace. Sin embargo, la principal ventaja es que manejará correctamente los constructores con parámetros opcionales C# 4.0, algo que Activator no hará.

protected T GetObject(params object[] args) 
{ 
    return (T)Impromptu.InvokeConstructor(typeof(T), args); 
} 
4

para conseguir este he intentado siguiente código:

protected T GetObject<T>() 
    { 
     T obj = default(T); 
     obj =Activator.CreateInstance<T>(); 
     return obj ; 
    } 
Cuestiones relacionadas