Existe-t-il un moyen élégant d'instancier un type de variable avec des paramètres?

StackOverflow https://stackoverflow.com/questions/96541

  •  01-07-2019
  •  | 
  •  

Question

Ce n'est pas légal:

public class MyBaseClass
{
  public MyBaseClass() {}
  public MyBaseClass(object arg) {}
}


public void ThisIsANoNo<T>() where T : MyBaseClass
{
  T foo = new T("whoops!");
}

Pour ce faire, vous devez réfléchir au type d'objet de T ou utiliser Activator.CreateInstance. Les deux sont assez méchants. Y a-t-il un meilleur moyen?

Était-ce utile?

La solution

Vous ne pouvez pas contraindre T à avoir une signature de constructeur particulière autre qu'un constructeur vide, mais vous pouvez contraindre T à avoir une méthode de fabrique avec la signature souhaitée:

public abstract class MyBaseClass
{
    protected MyBaseClass() {}
    protected abstract MyBaseClass CreateFromObject(object arg);
}

public void ThisWorksButIsntGreat<T>() where T : MyBaseClass, new()
{
    T foo = new T().CreateFromObject("whoopee!") as T;
}

Toutefois, je suggérerais peut-être d'utiliser un modèle de création différent, tel que Abstract Factory, pour ce scénario.

Autres conseils

Nope. Si vous ne transmettez pas de paramètres, vous pouvez alors contraindre votre type param à exiger un constructeur sans paramètre. Mais si vous devez passer des arguments, vous n’avez pas de chance.

where T : MyBaseClass, new()

fonctionne uniquement avec un constructeur public sans paramètre. au-delà, revenons à activator.CreateInstance (qui n’est vraiment pas si mauvais).

Je vois que cela ne fonctionne pas.

Mais qu'est-ce qui vous empêche de faire cela?

public void ThisIsANoNo<T>() where T : MyBaseClass
{
  MyBaseClass foo = new MyBaseClass("whoops!");
}

Puisque tout va hériter de MyBaseClass, il s'agira toujours de MyBaseClass, non?

Je l'ai essayé et cela fonctionne.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ThisIsANoNo<MyClass>();
            ThisIsANoNo<MyBaseClass>();
        }

        public class MyBaseClass
        {
            public MyBaseClass() { }
            public MyBaseClass(object arg) { }
        }

        public class MyClass :MyBaseClass
        {
            public MyClass() { }
            public MyClass(object arg, Object arg2) { }
        }

        public static void ThisIsANoNo<T>() where T : MyBaseClass
        {
            MyBaseClass foo = new MyBaseClass("whoops!");
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top