web-dev-qa-db-fra.com

C # Créer nouveau T()

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.

142
Hanshan

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);
}
370
Alex Aza

Pourquoi personne n'a suggéré Activator.CreateInstance?

http://msdn.Microsoft.com/en-us/library/wccyzw83.aspx

T obj = (T)Activator.CreateInstance(typeof(T));
56
Steve

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);
}
28
Sean Thoman

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.

18
Joel Coehoorn

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));
    }
}
14
Lukas Cenovsky

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);
}
7
jbtule

Pour obtenir cela, j'ai essayé le code suivant:

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