2013-09-23 3 views
12

Ich habe eine explizite Konvertierung vom Typ Bar zum Typ Foo definiert.IEnumerable <T> .Cast funktioniert nicht, selbst wenn ein expliziter Umwandlungsoperator definiert ist?

public class Bar 
{ 
    public static explicit operator Foo(Bar bar) 
    { 
    return new Foo(bar.Gar); 
    } 
} 

public class Foo 
{ 
    public string Gar { get; set; } 

    public Foo() { } 

    public Foo(string gar) { Gar = gar; } 
} 

Allerdings, wenn ich tun:

using System.Linq; 

... 

var manyFoos = manyBars.Cast<Foo>(); 

Es löst eine Ausnahme sagen, dass es nicht werfen kann.

Wie kann ich Cast mitteilen, dass ich meinen Umwandlungsoperator verwenden soll?

+1

Sie haben 'Bar'-> 'foo' Umwandlung definiert, sondern versuchen, das Gegenteil zu tun. – MarcinJuraszek

+0

Danke. Entschuldigung, ich meinte das Gegenteil. Ich habe diesen Code direkt in die Website eingegeben, ohne zu viel nachzudenken. Ich habe die Korrektur vorgenommen. –

+2

Immer noch nicht korrekt. 'bar.Gar'? woher kommt das? Bar hat keine Eigenschaft 'Gar' –

Antwort

2

Verwendung Select:

var manyFoos = manyBars.Select(bar => (Foo)bar); 
+0

Ich weiß, dass ich das tun kann. Vielen Dank. Ich frage nicht, wie ich projizieren soll. Ich frage - wie kann ich meinen Darsteller benutzen? Oder wie verwende ich einen anderen eingebauten Typ, um meine Besetzung zu verwenden, ohne manuell projizieren/auswählen/transformieren zu müssen? –

1

Ihr Code eigentlich nicht kompilieren. Ich nehme an, dass es in der Klasse "Bar" auch eine Eigenschaft "Gar" gibt?

public class Bar 
    { 
     public string Gar { get; set; } 

     public static explicit operator Foo(Bar bar) 
     { 
      return new Foo(bar.Gar); 
     } 
    } 

    public class Foo 
    { 
     public string Gar { get; set; } 

     public Foo() { } 

     public Foo(string gar) { Gar = gar; } 
    } 

static void Main(string[] args) 
     { 

      List<Bar> bars = new List<Bar>(); 
      for (int i = 0; i < 10; i++) 
       bars.Add(new Bar() { Gar = i.ToString() }); 

      var result = bars.Cast<Foo>(); 
     } 

+

I encaurage Sie Kovarianz zu lesen.

Angenommen, A ist in B konvertierbar, X ist kovariant, wenn X<A> in X<B> konvertierbar ist.

Mit C# 's Konzept der Kovarianz (und Kontravarianz) bedeutet "konvertierbar" konvertierbar über eine implizite Referenzkonvertierung wie A Unterklasse B oder A, die B implementiert. Numerische Konvertierungen, Boxkonvertierungen und benutzerdefinierte Konvertierungen sind nicht enthalten.

Sie müssen das mit Schnittstellen tun.

4

Die linq Cast Methode im Wesentlichen tut eine Box und entpacken. Es sind keine impliziten oder expliziten Cast-Operatoren bekannt, die in C# definiert sind, und der Compiler behandelt Standardmethodenaufrufe.

Sie müssten so etwas tun:

var manyFoos = manyBars.Select(bar => (Foo)bar); 
+0

Danke. Ich hatte nur gehofft, dass eine eingebaute Methode oder Erweiterung wie "Cast" oder "OfType" meine Besetzung verwendet, weil ich oft auf diese Situation gestoßen bin. Ich werde sowieso eine Transformation für jetzt verwenden. –

+0

@ WaterCoolerv2 Sie könnten wahrscheinlich Ihre eigene Erweiterungsmethode schreiben, vielleicht eine, die Reflexion verwendet. Aber das wäre weder so elegant noch effizient wie das, wonach Sie suchen. Ich würde bei dieser Methode bleiben, wenn du nicht wirklich dynamische Castings machst. –

+0

Danke, @ p.s.w.g. Nett. –

8

Guss Operatoren sind statische Methoden, die die Compiler Anrufe, wenn Sie Abgüsse im Code verwenden. Sie können nicht dynamisch verwendet werden. Enumerable.Cast führt eine Laufzeitumwandlung von zwei unbeschränkten generischen Typen durch, sodass während der Kompilierzeit nicht bekannt ist, welche Umsetzungsoperatoren verwendet werden sollen. Zu tun, was Sie wollen, können Sie Select verwenden:

manyFoos.Select(foo => (Bar)foo); 
+0

Danke. Ich bin mir bewusst, wie ich es mithilfe einer Projektion umgehen kann. Ich dachte nur, es wäre nett für 'Cast' oder' OfType' gewesen, obwohl ich hier nicht filtere und 'OfType' wäre nicht passend, sollte unsere benutzerdefinierte Besetzung verwenden. Danke für die Antwort. –

4

Wie alle anderen Antworten spitzer Typ ist nicht in der Kompilierung bekannt, da Cast Methode ist nicht generic. Es enthält den Typ object und führt eine explizite Umwandlung in T durch. Dies schlägt fehl, weil Sie keinen Konvertierungsoperator von object zu Foo haben. Und das ist auch nicht möglich.

Hier ist eine Arbeit rund um die Verwendung von Dynamiken, in denen die Umwandlung in Laufzeit durchgeführt wird.

public static class DynamicEnumerable 
{ 
    public static IEnumerable<T> DynamicCast<T>(this IEnumerable source) 
    { 
     foreach (dynamic current in source) 
     { 
      yield return (T)(current); 
     } 
    } 
} 

verwenden Sie es dann wie

var result = bars.DynamicCast<Foo>();//this works 
+0

Danke. Ich kann meine eigene Erweiterung schreiben. Ich hatte nur gehofft, dass es einen Weg für 'Cast' gibt, die Erweiterung, die meinen Operator nutzt. –

+0

@ WaterCoolerv2 Willkommen. Aber leider AFAIK gibt es keine eingebaute Methode :( –

+0

Danke. :-) Ich sage noch nicht, dass es sein sollte. Ich sage nur - der Zweck, diese Frage zu stellen war - Ich mache das schon seit Jahren und das ist einer meiner ärgsten Ärger und ich bekam nie die Chance zu fragen, ob ich 'Cast' umdrehen könnte Gehorche meinem Betreiber. Erscheint nicht. :-) –

Verwandte Themen