Zuerst würde ich eine Einschränkung der Klasse hinzufügen fordern, dass T
muss Typ Base
:
class Base { }
class Derived : Base { }
class Wrapper<T> where T : Base // T must be (derived from) Base
{
public T Value { get; }
public Wrapper (T value) { Value = value; }
}
Zweitens eine generische Wandler gefährlich wäre. Was passiert, wenn jemand versucht, eine Wrapper<Gnu>
in eine Wrapper<Lion>
umzuwandeln?
Also würde ich einen Schritt zurück und einen nicht-generic-Wandler machen, die einfach zu Wrapper<Base>
konvertiert:
public Wrapper<Base> ToBase()
{
return new Wrapper<Base>(Value);
}
Und dies funktioniert, weil der Zwang für T
auf Klassenebene.
C# ist eigentlich eine Sprache, die für ein hohes Maß an Sicherheit bekannt ist. Aber man kann es umgehen und tun, was Sie in dem Kommentar gefragt durch irgendwelche Zwänge ommitting und nur versuchen, zu werfen, was kommt in:
public Wrapper<TResult> To<TResult>() where TResult : class
{
return new Wrapper<TResult>(Value as TResult);
}
Sie benötigen den class
Zwang und den as
Operator, weil eine direkte Besetzung zwischen zwei generische Parameter sind nicht kompilierbar (da die IL zu sehr von den spezifischen Typen abhängt).
Aber dies wird Wrapper
Instanzen mit Value
auf null
zurückgeben, wenn die Typen nicht übereinstimmen. Und es wird mit abgeleiteten Typen anstelle von Basistypen auch funktionieren. Also pass auf dich auf. Sie können dafür zusätzliche Prüfungen hinzufügen.Und kümmern sich um die Gnus :)
UPDATE:
Ein sicherer Weg:
public Wrapper<TResult> To<TResult>() where TResult : class// TResult must also be (derived from) Base
{
if (!typeof(TResult).IsAssignableFrom(typeof(T)))
throw new InvalidCastException();
return new Wrapper<TResult>(Value as TResult);
}
Diese prüft, ob T
von TResult
abgeleitet ist und löst eine InvalidCastException
, wenn nicht. Sie können das für Ihre Bedürfnisse verfeinern.
Haben Sie versucht, 'Wrapper Wrapper = new Wrapper (neu Derived());'? –
Eli
Das würde funktionieren, wenn Sie im Voraus ein Objekt erstellen, aber in Fällen, in denen es so aussieht: 'var wrapper = new Wrapper (new Derived());/* Irgendein anderer Code/*/var newWrapper = Wrapper; 'wird es nicht. –