Angenommen, Sie sprechen von einer Vorlagenspezialisierung, wie sie mit C ++ - Vorlagen möglich ist - eine solche Funktion ist in C # nicht wirklich verfügbar. Dies liegt daran, dass C # -Generika während der Kompilierung nicht verarbeitet werden und eher ein Merkmal der Laufzeit sind.
Mit C # 3.0-Erweiterungsmethoden können Sie jedoch einen ähnlichen Effekt erzielen. Hier ist ein Beispiel, das zeigt, wie eine Erweiterungsmethode nur für den MyClass<int>
Typ hinzugefügt wird, ähnlich wie bei der Vorlagenspezialisierung. Beachten Sie jedoch, dass Sie dies nicht verwenden können, um die Standardimplementierung der Methode auszublenden, da der C # -Compiler immer Standardmethoden gegenüber Erweiterungsmethoden bevorzugt:
class MyClass<T> {
public int Foo { get { return 10; } }
}
static class MyClassSpecialization {
public static int Bar(this MyClass<int> cls) {
return cls.Foo + 20;
}
}
Jetzt können Sie Folgendes schreiben:
var cls = new MyClass<int>();
cls.Bar();
Wenn Sie einen Standardfall für die Methode haben möchten, der verwendet wird, wenn keine Spezialisierung angegeben ist, sollte meiner Meinung nach das Schreiben einer generischen Bar
Erweiterungsmethode den Trick tun:
public static int Bar<T>(this MyClass<T> cls) {
return cls.Foo + 42;
}
static
Methoden, die einen generischen Typ annehmen. Das heißt, das Problem, auf das in der Antwort von @MarcGravell hingewiesen wird, scheint umgangen zu werden, indem die Methode basierend auf einem Argument wieMyClass<T>
/ "templiert" wirdMyClass<int>
, anstatt die Methode auf den spezifischen "Datentyp" (T
/int
) zu templieren .void CallAppropriateBar<T>() { (new MyClass<T>()).Bar(); }
.Durch Hinzufügen einer Zwischenklasse und eines Wörterbuchs ist eine Spezialisierung möglich .
Um uns auf T zu spezialisieren, erstellen wir eine generische Schnittstelle mit einer Methode namens (zB) Apply. Definieren Sie für die spezifischen Klassen, für die diese Schnittstelle implementiert ist, die für diese Klasse spezifische Methode. Diese Zwischenklasse wird als Merkmalsklasse bezeichnet.
Diese Merkmalsklasse kann als Parameter im Aufruf der generischen Methode angegeben werden, die dann (natürlich) immer die richtige Implementierung benötigt.
Anstatt es manuell anzugeben, kann die Merkmalsklasse auch in einer globalen Klasse gespeichert werden
IDictionary<System.Type, object>
. Es kann dann nachgeschlagen werden und voila, Sie haben dort echte Spezialisierung.Wenn es Ihnen passt, können Sie es in einer Erweiterungsmethode verfügbar machen.
Unter diesem Link zu meinem letzten Blog und den Folgemaßnahmen finden Sie eine ausführliche Beschreibung und Beispiele.
quelle
Ich suchte nach einem Muster, um auch die Spezialisierung von Vorlagen zu simulieren. Es gibt einige Ansätze, die unter bestimmten Umständen funktionieren können. Was ist jedoch mit dem Fall?
Es wäre möglich, die Aktion mit Anweisungen zu wählen, z
if (typeof(T) == typeof(int))
. Es gibt jedoch eine bessere Möglichkeit, die Spezialisierung realer Vorlagen mit dem Aufwand eines einzelnen virtuellen Funktionsaufrufs zu simulieren:Jetzt können wir schreiben, ohne den Typ vorher kennen zu müssen:
Wenn die Spezialisierung nicht nur für die implementierten Typen, sondern auch für abgeleitete Typen aufgerufen werden soll, könnte man einen
In
Parameter für die Schnittstelle verwenden. In diesem Fall können die Rückgabetypen der Methoden jedoch nicht mehr vom generischen TypT
sein.quelle
if (type == typeof(int))
und dann zum generischen Typ mit zusätzlichem Boxen / Unboxing zurückkehrenreturn (T)(object)result;
(weil der Typ nur logisch bekannt ist, nicht statisch bekannt)Einige der vorgeschlagenen Antworten verwenden Laufzeittypinformationen: von Natur aus langsamer als Methodenaufrufe, die an die Kompilierungszeit gebunden sind.
Der Compiler erzwingt die Spezialisierung nicht so gut wie in C ++.
Ich würde empfehlen, in PostSharp nach einer Möglichkeit zu suchen, Code einzufügen, nachdem der übliche Compiler ausgeführt wurde, um einen ähnlichen Effekt wie C ++ zu erzielen.
quelle
Ich denke, es gibt eine Möglichkeit, dies mit .NET 4+ mithilfe der dynamischen Auflösung zu erreichen:
Ausgabe:
Dies zeigt, dass für verschiedene Typen eine andere Implementierung erforderlich ist.
quelle
Wenn Sie nur testen möchten, ob ein Typ von XYZ abgeleitet ist, können Sie Folgendes verwenden:
In diesem Fall können Sie "theunknownobject" in XYZ umwandeln und alternativeFunc () wie folgt aufrufen:
Hoffe das hilft.
quelle
"c++ template specialization"