Question C # Créer un nouveau T ()


Vous pouvez voir ce que j'essaie (mais échoue) à 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 jouais avec une classe de contrôleurs personnalisés pour tous les contrôleurs, avec des méthodes standardisées. Donc, dans le contexte, je devais créer une nouvelle instance de l'objet du type de contrôleur. Donc, au moment d'écrire, c'était quelque chose comme:

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

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

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

        return View(obj);
    }

Et donc j'ai décidé que la réflexion était la plus facile ici. Je suis d'accord que, étant donné l'énoncé initial de la question, la réponse la plus appropriée à marquer comme étant correcte était celle utilisant la contrainte new (). J'ai corrigé cela.


116
2018-06-30 03:16


origine


Réponses:


Jeter un coup d'œil à 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 déclaration invalide. le new() la contrainte dit 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 passer des paramètres:

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

319
2018-06-30 03:19



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

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

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

43
2018-06-30 04:15



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
2018-06-30 03:22



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 exiger ou utiliser les paramètres disponibles, si nécessaire.


17
2018-06-30 03:49



le nouvelle contrainte c'est bien, mais si vous avez besoin de T comme type de valeur, utilisez ceci:

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

13
2018-06-30 10:22



Comme il est marqué C # 4. Avec le framework open sourece ImpromptuIntereface il utilisera le dlr pour appeler le constructeur, il est beaucoup plus rapide que Activator lorsque votre constructeur a des arguments, et de manière négligeable lorsque ce n'est pas le cas. Cependant, le principal avantage est qu'il traitera correctement les constructeurs avec les paramètres optionnels C # 4.0, ce que ne fera pas Activator.

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

7
2018-06-30 14:20



Pour l'obtenir j'ai essayé le code suivant:

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

3
2017-12-06 04:39