Laden...

T als Returnwert - Verständnisproblem

Erstellt von Glowhollow vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.727 Views
G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren
T als Returnwert - Verständnisproblem

Hi,

es taucht ja in diversen Dokumentationen der Typ <T> auf. Ich bin jetzt bisher immer davon ausgegangen, das das ein Platzhalter für den Typ ist - also string, int, whatever.

Jetzt bin ich jedoch in einem Code über das hier gestolpert.


public static T function<T>(this string value)

Bedeutet das, das der Typ "wildcard"-mäßig gesetzt werden kann ?

Mag mir jemand das kurz erklären ?

4.931 Beiträge seit 2008
vor 5 Jahren

Das nennt sich Generika (bzw auf englisch "Generics").
Und statt T kann jeder beliebige Name verwendet werden (es hat sich nur T für Type naheliegenderweise eingebürgert).
Und innerhalb der Klasse bzw. Methode wird dann dieser Name als Platzhalter für den konkreten Typ verwendet (welche dann der Compiler bei der Benutzung ersetzt).

Bei deiner genannten Methode hat also die Methode je nach Aufruf den entsprechenden Rückgabetyp:


string s = "...";
int i = s.function<int>();
float f = s.function<float>();

3.003 Beiträge seit 2006
vor 5 Jahren

Ergänzung: der Typ lässt sich auch eingrenzen, was dann direkt zur Entwurfszeit für Fehler sorgt, wenn man sich nicht an die Eingrenzung hält:


public T GetValue<T>(Func<T> createReturnValue) where T: MyAbstractBaseType
{
    return createReturnValue();
}

Der Compiler kann auch anhand des Typen, der dann beim Aufruf benutzt wird, erkennen, welcher Typ T gemeint ist, so dass man die spitzen Klammern dann weglassen kann:


var myValue = GetValue(() => new ConcreteExample());

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

F
10.010 Beiträge seit 2004
vor 5 Jahren
G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

ok, lese ich mir durch, versprochen...

Jedoch habe ich noch eine kleine programmiertechnsiche Frage... Vielleicht weiß die ja jemand aus dem Effeff.

ich habe eine Funktion die auf eine klasse referenziert.


Funktion<klasse>

Ist es möglich, die klasse über generika so zu definieren, das ich eine Funktion habe, die mir eine klasse zurückliefert und diese dort einsetzt.

Im prinzip etwa so


public T GetClassByName(String klassenname)
{
...
return T
}

und ich dann schreibe...


Funktion<GetClassByName(klassenname)>

Würde das funktionieren ?

Umsetzung mach ich noch, da bin ich dran.

2.207 Beiträge seit 2011
vor 5 Jahren

Hallo Glowhollow,

was hast du denn vor?

Wenn du willst, das x Klassen dir eine Funktion anbieten ohne von aussen zu wissen, welche Klasse das ist, definier dir ein normales Interface und lass die Klassen das implementieren.

Gruss

Coffeebean

3.170 Beiträge seit 2006
vor 5 Jahren

Hallo,

@Glowhollow,
was Du da vorhast, geht so nicht.*
Das erstellen generischer Objekten und der Aufruf generischer Funktionen erfordern, dass die konkreten Typen, die für die Typargumente eingesetzt werden, zur Compilezeit feststehen (und nicht erst zur Laufzeit).

*Sowas kann man theoretisch dann über Reflection und den Emitter auch zur Laufzeit erzeugen - aber das hier durchzukauen wäre wohl etwas am Thema vorbei.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

hi coffeebean,

also, nachdem ich ja den newtonSoft JSON Deserialisierer nicht nutzen kann, und der JavaScriptDeserialisierer in meinem Fall nicht zu gebrauchen ist; könnte hier etwas genauer ins detail gehen, aber fakt ist, der funktioniert mit meinem Input nicht richtig - muß ich einen eigenen Deserialisierer bauen.

Ich habe einen parser, der eine eingeschränkte Deserialisierungsfunktion hat, solange das nur auf "einer" ebene ist.

Das heißt, Properties (beliebige Anzahl) kann der Parser an die Klasse weiterleiten und befüllen.

Jetzt ist das jedoch nur ein "ausschnitt", des gesamten JSON Strings. Im Prinzp brauch ich eine "rekursive" funktion, die den kompletten JSON String durchläuft, ihn an den Parser übergibt, dieser dann die klassen befüllt, so das ich am ende, alles deserialisert habe.

Um es mal mit Code darzustellen:

einen teilstring wie:


{"made_sla": "true"}

bekomme ich deserialisiert


{"resolved_by": {
        "link": "https://dev64321.service-now.com/api/now/table/sys_user/5137153cc611227c000bbd1bd8cd2007",
        "value": "5137153cc611227c000bbd1bd8cd2007"
      }
}

das auch, wobei ich hier schon einen zwischenschritt einbauen muß, da der parser hier nur einen String bestehend aus ""link": "https://dev64321.service-now.com/api/now/table/sys_user/5137153cc611227c000bbd1bd8cd2007","value": "5137153cc611227c000bbd1bd8cd2007"" zurückliefert.

Im prinzp versuch ich mich jetzt durch den JSON String "durchzuhangeln", in dem ich den ersten value, als klasse übergebe, diese soweit befüllen lasse und später dann, diese referenz benutze, um den zurückgegeben String erneut zu deserialisieren.

Die Funktion heißt FromJson<class>. Returnvalue ist eine generika. Da die Klassen mit getter und setter befüllt sind, werden diese natürlich mit werten befüllt, ganz so wie ich es brauche.

Ich bin dabei den deserialisierer per hand zu schreiben. daher die anfrage über den funktionsumfang.

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

@Marsstein...

Naja, ich will die ja nicht zur Laufzeit ansprechen, bzw. genereieren. Diese Klassen bestehen schon, ich müßte nur referenzieren. Da ich aber unterschiedliche Klassen referenzieren muß (die sind ein bischen verschachtelt), wäre es toll, wenn ich diese mit einer "getClassByName" funktion als Generika übergeben könnte.

3.170 Beiträge seit 2006
vor 5 Jahren

Hallo,

genau das meine ich aber mit:

dass die konkreten Typen, die für die Typargumente eingesetzt werden, zur Compilezeit feststehen

Die kannst Du eben nicht aus einer Funktion heraus erzeugen, da der Compiler den Code dieser Funktion ausführen müsste, damit der Typ zur Compilezeit bekannt wäre. Das kann und tut er aber nicht. Daher müssen die konkreten Typen bei Nutzung von Generics direkt im Code angegeben werden und nicht dynamisch (per Code) irgendwo hergezaubert werden.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

G
Glowhollow Themenstarter:in
74 Beiträge seit 2018
vor 5 Jahren

jetzt hab ichs kapiert danke. Stimmt ist klar. Woher soll der Compiler das wissen.