Vous pouvez voir ce que j'essaie (mais échoue) de faire avec le code suivant:
protected T GetObject()
{
return new T();
}
Toute aide serait grandement appréciée.
MODIFIER:
Le contexte était le suivant. Je m'amusais avec une classe de contrôleurs personnalisés pour tous les contrôleurs, avec des méthodes normalisées. Donc, dans le contexte, je devais créer une nouvelle instance de l'objet du type contrôleur. Au moment de la rédaction de cet article, cela ressemblait à:
public class GenericController<T> : Controller
{
...
protected T GetObject()
{
return (T)Activator.CreateInstance(ObjectType);
}
public ActionResult Create()
{
var obj = GetObject()
return View(obj);
}
Et j'ai donc décidé que la réflexion était la plus facile ici. Je conviens que, compte tenu de l'énoncé initial de la question, la réponse la plus appropriée pour marquer comme correcte était celle qui utilisait la contrainte new (). J'ai corrigé ça.
Jetez un oeil à nouvelle contrainte
public class MyClass<T> where T : new()
{
protected T GetObject()
{
return new T();
}
}
T
pourrait être une classe qui n'a pas de constructeur par défaut: dans ce cas, new T()
serait une instruction non valide. La contrainte new()
indique que T
doit avoir un constructeur par défaut, ce qui rend new T()
légal.
Vous pouvez appliquer la même contrainte à une méthode générique:
public static T GetObject<T>() where T : new()
{
return new T();
}
Si vous devez transmettre des paramètres:
protected T GetObject(params object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
Pourquoi personne n'a suggéré Activator.CreateInstance
?
http://msdn.Microsoft.com/en-us/library/wccyzw83.aspx
T obj = (T)Activator.CreateInstance(typeof(T));
Une autre façon consiste à utiliser la réflexion:
protected T GetObject<T>(Type[] signature, object[] args)
{
return (T)typeof(T).GetConstructor(signature).Invoke(args);
}
Juste pour terminer, la meilleure solution consiste souvent à exiger un argument de fonction d'usine:
T GetObject<T>(Func<T> factory)
{ return factory(); }
et appelez ça quelque chose comme ça:
string s = GetObject(() => "result");
Vous pouvez l'utiliser pour demander ou utiliser les paramètres disponibles, si nécessaire.
La nouvelle contrainte convient, mais si vous avez aussi besoin que T soit un type valeur, utilisez ceci:
protected T GetObject() {
if (typeof(T).IsValueType || typeof(T) == typeof(string)) {
return default(T);
} else {
return (T)Activator.CreateInstance(typeof(T));
}
}
Comme ceci est étiqueté C # 4. Avec le cadre open sourece ImpromptuIntereface , il utilisera dlr pour appeler le constructeur. Il est nettement plus rapide que Activator lorsque votre constructeur dispose d’arguments, et d’une lenteur négligeable s’il ne le fait pas. Cependant, le principal avantage est qu'il gère correctement les constructeurs avec les paramètres facultatifs C # 4.0, ce qu'Activator ne fera pas.
protected T GetObject(params object[] args)
{
return (T)Impromptu.InvokeConstructor(typeof(T), args);
}
Pour obtenir cela, j'ai essayé le code suivant:
protected T GetObject<T>()
{
T obj = default(T);
obj =Activator.CreateInstance<T>();
return obj ;
}