Laden...

Generics und abstrakte Klasse

Erstellt von Lordas vor 15 Jahren Letzter Beitrag vor 15 Jahren 6.526 Views
L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren
Generics und abstrakte Klasse

[EDIT=herbivore]Abgeteilt von Generics: Typparameter zu Laufzeit festlegen[EDIT]

hallo zusammen,

speziell zu diesem thema hätte ich auch eine frage. dazu folgende situation in einer Klasse:


//Methode 1
public List<TMyObject> DoWork1<TMyObject>(string myString) where TMyObject : MyObject, new()
{
   //...
}


public void DoWork2(MyObject myObject)
{
   string myString = "irgendeinstring";
   //jetzt brauche ich die obige Methode und möchte Sie natürlich wie vorhanden nutzen
   IList list = this.GetType().GetMethod ("DoWork1").MakeGenericMethod (typeof (MyObject)).Invoke (this, new object[]{myString});
}


dort bekomme ich einen fehler, dass der parameter nicht zu TMyObject passt. ich habe auch schon einige andere varianten durchgespielt, aber nie hat es funktioniert. d.h. ich weiß nicht genau was ich bei Invoke(..., ...) in meinem fall einsetzen soll. außerdem weiß ich nicht ob ich wirklich auch meine IList so bereits zurückbekomme.

evtl. ist ja in der konstellation ein ganz anderer ansatz notwendig??

vielleicht kann mir jemand von euch helfen - wäre super!

2.891 Beiträge seit 2004
vor 15 Jahren

Hallo Lordas,

kann es sein, dass du einfach nur folgendes machen willst:


public void DoWork2(MyObject myObject)
{
   string myString = "irgendeinstring";
   IList list = DoWork1<MyObject>(myString );
}

Gruß,
dN!3L

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

nein, das funktioniert leider nicht, da MyMethod abstract ist.

2.891 Beiträge seit 2004
vor 15 Jahren
  1. Da steht nirgendwo "MyMethod" im deinem geposteten Code!?
  2. Aber genau das macht dein Invoke (weswegen es auch überflüssig ist).
  3. Du meinst sicher "MyObject" ist abstrakt. Wenn dem so ist, kannst du auch die generische Methode (egal wie) nicht mit "MyObject" als generischen Parameter aufrufen, weil du ja forderst, dass new() gehen muss.

Also, was genau hast du vor?

Gruß,
dN!3L

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

hi,

ja sorry - meinte natürlich MyObject.

wenn ich also den punkt 3. von dir richtig interpretiere habe ich überhaupt keine chance die generische Methode DoWork1<MyObject>(string myString) in dieser klasse aufzurufen, da ich zu diesem zeitpunkt nur die abstrakte klasse und nicht eine dazugehörige kindklasse kenne?

was ich noch nicht versucht habe ist möglichkeit mit Activator.CreateInstance() meine instanziierte kindklasse myObject nochmal neu über dessen typ zu erzeugen und das dann dort mit einzupflanzen.

allerdings habe ich auch schon versucht testweise meine kindklasse in dieser methode zu instanziieren und dort einzusetzen - auch fehlgeschlagen. also so:


MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();

IList list = this.GetType().GetMethod ("DoWork1").MakeGenericMethod (typeof (MyObject)).Invoke (myChildInstanceOfMyObject, new object[]{myString});

vielleicht füge ich zur erklärung nochmal ein paar codezeilen hinzu. ich möchte von außen folgenden aufruf starten (wobei davon auszugehen ist, dass die Methode DoWork1 und DoWork2 in der Klasse "Test" enthalten ist):


MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();

Test test = new Test();
test.DoWork2(myChildInstanceOfMyObject);


so, jetzt möchte ich die methode DoWork1 innerhalb der klasse Test und der Methode DoWork2 wie oben bereits geschildert aufrufen.

hab ich denn sonst eine chance das irgendwie umzusetzen?

vielen dank!

2.891 Beiträge seit 2004
vor 15 Jahren

Hallo Lordas,

egal was du versucht, du kannst als generischen Parameter einfach keine abstrakte Klasse nehmen - du hast in der generischen Methode ja selbst angegeben, dass new() als Bedingung gelten muss. (Geht's auch ohne new()?)

MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();  
Test test = new Test();  
test.DoWork2(myChildInstanceOfMyObject);  

Ah, da sieht sie Sache doch schon anders aus. Wie du schon geschrieben hast, weißt du in "DoWork2" noch nicht, welchen generischen Parameter du hast. Tja, dann lass es dir sagen, irgendein Aufrufer muss es ja wissen!

Zwei Möglichkeiten dafür:
Generische Methode

public void DoWork2<T>(MyObject myObject)
{
   string myString = "irgendeinstring";
   List<T> list = this.DoWork1<T>(myString);
}

Aufruf:

MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();
Test test = new Test();
test.DoWork2<MyObjectChildClass >(myChildInstanceOfMyObject);

Generische Klasse


class Test<T> 
{
   public void DoWork2(MyObject myObject)
   {
      string myString = "irgendeinstring";
      List<T> list = this.DoWork1<T>(myString);
   }
}

Aufruf:

MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();
Test test = new Test<MyObjectChildClass >();
test.DoWork2(myChildInstanceOfMyObject);

Gruß
dN!3L

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

heee, klar. danke schon mal dafür!!!

aber irgendwie hänge ich jetzt noch fest (bin einfach schon zu eingefahren heute abend). wie muss ich dann die MakeGenericMethod richtig aufrufen?

sorry für die bescheuerte fragerei, aber ich steig grad nicht mehr richtig durch 🤔

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

Generische Methode

public void DoWork2<T>(MyObject myObject)  
{  
   string myString = "irgendeinstring";  
   List<T> list = this.DoWork1<T>(myString);  
}  

Aufruf:

MyObjectChildClass myChildInstanceOfMyObject = new MyObjectChildClass();  
Test test = new Test();  
test.DoWork2<MyObjectChildClass >(myChildInstanceOfMyObject);  

das funktioniert leider nicht. X(
hier bekomme ich den fehler, dass T ein nicht abstrakter Typ mit einem öffentlichen parameterlosen Konstruktor sein muss.

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

sch... sorry war eben voll auf der leitung gesessen. hatte new() im constraint vergessen.

vielen dank nochmal für deine mühe - habe wieder mal einiges dazugelernt 😃

2.891 Beiträge seit 2004
vor 15 Jahren

Hallo Lordas,

ich nehme mal an, dass du jetzt eine richtige Lösung hast.
Aber nochmal explizit folgende Frage beantwortet:

wie muss ich dann die MakeGenericMethod richtig aufrufen?

Das brauchst du hier gar nicht, weil du den generischen Parameter ja schon zur Compilezeit kennst. Deswegen kann hier ganz normal Generics verwendet werden.

Gruß,
dN!3L

L
Lordas Themenstarter:in
63 Beiträge seit 2005
vor 15 Jahren

yo ist mir natürlich im nachhinein auch klar geworden - zumal du es ja in deinem beispiel auch richtig dargestellt hattest.