2017-05-12 2 views
0
interface ISample 
{ 
    int Id { get; set; } 
} 
public class MyClass : ISample 
{ 
    public int Id 
    { 
     get; 
     set; 
    } 
    public string Name { get; set; } 
} 

Das obige ist eine Klasse, die eine Schnittstelle ISample implementiert. Mit Generics habe ich die folgende Methode hinzugefügt, um ein Objekt eines gegebenen Typs in einen anderen Typ umzuwandeln.Generic C# Casting

private TResult Sample<TSource, TResult>(TSource source) 
      where TSource : TResult 
{ 
    return (TResult)(source); 
} 

mit Generics wie kann ich die Rückseite der gleichen erreichen, die ein Objekt Sie ausreichend gegeben ist, ich will es konvertieren zurück zu MyClass Objekt, in dem Sie ausreichend die TSource und TResult ist MyClass wo TResult TSource implementiert.

+5

Sie können dies nicht tun, denn wenn Sie eine Instanz von "ISample" haben, wer garantiert, dass es tatsächlich eine Instanz von 'MyClass' ist und nicht von irgendeiner anderen, die diese Schnittstelle implementiert? Wie auch immer, wieso hast du überhaupt diese Methode? Was macht es, was ein einfaches '(ISample) myInstanceOfMyClass' nicht für Sie tun wird? – HimBromBeere

+0

Wenn 'TSource' von 'TResult' erbt (was Sie dort eingerichtet haben), kann jedes Objekt vom Typ 'TSource' bereits implizit auf ein 'TResult' umgewandelt werden. Allerdings glaube ich, dass wenn Sie es invertieren ('TResult' erbt von' TSource'), dass Sie _etwas_ garantieren können, dass eine Konvertierung möglich ist; oder Sie werden zumindest einen Compilerfehler anstelle einer Laufzeitausnahme bekommen. – Flater

Antwort

1

Sie würden einfach von

where TSource : TResult 

zu

where TResult : TSource 

Ende mit Code wechseln haben, die aussehen könnte wie

private TResult ToInterface<TSource, TResult>(TSource source) where TSource : TResult 
{ 
    return source; 
} 

private TResult FromInterface<TSource, TResult>(TSource source) where TResult : TSource 
{ 
    return source as TResult; 
} 

Beachten Sie, dass die FromInterface Funktion ein werfen InvalidCastException, wenn der Parameter 'source' nicht vom Typ TResult ist oder nicht von TRes erbt Ult.


Edit:

Siehe Antwort von Lajos Arpad.

+0

Sie können den Cast 'as' verwenden, um die Ausnahme zu vermeiden und den Benutzer der Funktion entscheiden zu lassen, wie mit der ungültigen Besetzung verfahren wird, anstatt eine Ausnahme auszulösen. –

+0

Das ist richtig, aber die Frage war, eine generische Lösung für die Umwandlung zwischen Typen in einer Hierarchie zu erstellen, nicht mit ungültigen Umwandlungen umzugehen. Ich stimme zu, dass es nicht ideal ist. – fshauge

1

Der Compiler wird nicht im Voraus wissen, dass Sie Downcasting von TSource bis TResult durchführen möchten. Sie müssen Ihre TSource Instanz in etwas werfen, die sicherlich eine übergeordnete Klasse von TResult ist, so dass Sie TSource-object zuerst werfen müssen:

(TResult)((object)source) 

EDIT:

Wie bereits ausgeführt im Kommentarbereich durch @ Zdeněk Jelínek, Eric Lippert hat einen Blog geschrieben post about dies.

+1

Ihre Lösung ist richtig. Eric Lippert hat darüber mit ausführlicheren Erklärung gebloggt: https://ericlippert.com/2015/10/14/casts-and-type-parameters-do-not-mix/ –

+1

@ ZdeněkJelínek Vielen Dank für Ihre Eingabe, die ich habe fügte diese wertvollen Details der Antwort hinzu. –