2008-09-18 10 views
-1

Ce n'est pas légal:Existe-t-il un moyen élégant d'instancier un type de variable avec des paramètres?

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 faire une réflexion sur l'objet de type T ou vous devez utiliser Activator.CreateInstance. Les deux sont plutôt méchants. Y a-t-il un meilleur moyen?

Répondre

1

Vous ne pouvez pas contraindre T avoir une signature constructeur particulier autre qu'un constructeur vide, mais vous pouvez contraindre T d'avoir une méthode de fabrication 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; 
} 

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

0
where T : MyBaseClass, new() 

fonctionne uniquement avec un constructeur public sans paramètre. au-delà, retour à activator.CreateInstance (ce qui n'est vraiment pas si mal).

+0

pas de manière générique. –

2

Non. Si vous ne transmettiez pas de paramètres, vous pourriez contraindre votre type param à exiger un constructeur sans paramètre. Mais, si vous avez besoin de passer des arguments, vous n'avez pas de chance.

-2

Je peux voir que cela ne fonctionne pas.

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

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

Puisque tout va hériter de MyBaseClass ils al MyBaseClass être, 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!"); 
     } 
    } 
} 
+0

Que se passe-t-il si vous avez une classe dérivée qui a seulement un constructeur qui prend 2 arguments? –

+0

Cette méthode ne retournera jamais les objets de type T, seulement les objets de type MyBaseClass. –

+0

c'est un vide, ça ne retourne rien. et un casting peut résoudre ce problème. – chrissie1