Există o modalitate elegantă de a instanțiza un tip de variabilă cu parametri?

Acest lucru nu este legal:

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


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

Pentru a face acest lucru, trebuie să faceți o anumită reflecție asupra obiectului de tip pentru T sau trebuie să utilizați Activator.CreateInstance. Ambele sunt destul de urât. Există o cale mai bună?

0

4 răspunsuri

where T : MyBaseClass, new()

funcționează numai cu constructor public fără parametri. dincolo de asta, înapoi la activator.CreateInstance (care într-adevăr nu este THAT rău).

0
adăugat
nu într-un mod generic.
adăugat autor Darren Kopp, sursa

Văd că nu funcționează.

Dar ce te oprește să faci asta?

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

Deoarece totul va moșteni de la MyBaseClass, ei vor fi MyBaseClass, nu?

Am încercat și asta funcționează.

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

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

        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() where T : MyBaseClass
        {
            MyBaseClass foo = new MyBaseClass("whoops!");
        }
    }
}
0
adăugat
T este o extensie a MyBaseClass. Puteți crea o instanță a lui MyBaseClass, dar nu o puteți "transforma" în T, deoarece nu este un T. În plus, implementarea dvs. ThisIsANoNo, în timp ce are o semnătura generică, nu face o nouă instanță a tip variabilă.
adăugat autor Will, sursa
este un gol, nu întoarce nimic. iar o distribuție poate rezolva asta.
adăugat autor chrissie1, sursa
@ Am încercat și funcționează.
adăugat autor chrissie1, sursa
Ce se întâmplă dacă aveți o clasă derivată care are doar un constructor care ia 2 argumente?
adăugat autor Abe Heidebrecht, sursa
Această metodă nu va returna niciodată obiecte de tip T, numai obiecte de tip MyBaseClass.
adăugat autor Matt Howells, sursa

Nu. Dacă nu ați trecut parametrii, puteți constrânge paramul de tip pentru a solicita un constructor fără parametri. Dar, dacă trebuie să treci argumente, nu ai noroc.

0
adăugat

Nu puteți constrânge T să aibă o altă semnătură de constructor decât un constructor gol, dar puteți constrânge T să aibă o metodă din fabrică cu semnătura dorită:

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

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

Cu toate acestea, aș sugera probabil folosirea unui alt tip de creare, cum ar fi Fabrica de Rezumat pentru acest scenariu.

0
adăugat