2013-09-23 20 views
12

Ho una conversione esplicita definita dal tipo Bar per digitare Foo.IEnumerable <T> .Cast non funziona anche se è definito un operatore di cast esplicito?

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; } 
} 

Tuttavia, quando lo faccio:

using System.Linq; 

... 

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

viene generata un'eccezione dicendo che non può lanciare.

Come faccio a comunicare allo Cast l'operatore di trasmissione per provare la conversione?

+1

Hai 'Bar'->' conversione foo' definito, ma cercando di fare il contrario. – MarcinJuraszek

+0

Grazie. Scusa, volevo dire il contrario. Ho appena digitato quel codice direttamente nel sito web senza pensarci troppo. Ho fatto la correzione. –

+2

Ancora non corretto. 'Bar.Gar'? da dove viene questo? il bar non ha la proprietà 'Gar' –

risposta

2

Uso Select:

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

So che posso farlo. Grazie. Non sto chiedendo come proiettare. Ti sto chiedendo: come faccio a utilizzare Cast il mio operatore di cast? O come faccio a fare in modo che un altro tipo incorporato usi il mio cast senza dover proiettare/selezionare/trasformare manualmente? –

1

Il codice in realtà non compilazione. Suppongo che ci sia una proprietà "Gar" anche nella classe "Bar"?

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>(); 
     } 

+

ho encaurage di leggere su covarianza.

Supponendo che A sia convertibile in B, X è covariante se è convertibile in X<B>.

Con la nozione di covarianza (e controvarianza) di C#, "convertibile" significa convertibile tramite una conversione di riferimento implicita, come A sottoclassi B, o A implementazione B. Conversioni numeriche, conversioni di boxe e conversioni personalizzate non sono incluse.

Devi farlo con le interfacce.

4

Il metodo linq Cast essenzialmente esegue una casella e un unbox. Non è a conoscenza di operatori di cast impliciti o espliciti definiti in C#, che il compilatore tratta le chiamate di metodo standard.

Avresti per fare qualcosa di simile:

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

Grazie. Speravo solo di avere un metodo o un'estensione incorporata come 'Cast' o' OfType' usare il mio cast perché molte volte mi sono imbattuto in questa situazione. Ad ogni modo userò una trasformazione per ora. –

+0

@ WaterCoolerv2 Probabilmente potresti scrivere il tuo metodo di estensione, forse uno che usa la riflessione. Ma quello non sarebbe né elegante né efficiente come quello che probabilmente stai cercando. Continuerò con questo metodo a meno che * davvero * non faccia casting dinamico. –

+0

Grazie, @ p.s.w.g. Bello. –

8

operatori cast sono metodi statici che le compilatore chiamate quando si utilizza calchi in codice. Non possono essere usati dinamicamente. Enumerable.Cast esegue un cast runtime di due tipi generici non vincolati, quindi non può sapere durante il periodo di compilazione che gli operatori cast devono utilizzare. Per fare ciò che si desidera, è possibile utilizzare Select:

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

Grazie. Sono consapevole di come aggirarlo usando una proiezione. Stavo solo pensando che sarebbe stato bello per 'Cast' o' OfType', anche se non sto filtrando qui e 'OfType' non sarebbe appropriato, dovrei usare il cast personalizzato. Grazie per la risposta, però. –

4

Come tutte le altre risposte di tipo punta non è noto in fase di compilazione in quanto Cast metodo non è generic. Detiene il tipo di object e crea un cast esplicito su T. ciò non riesce perché non si dispone di operatore di conversione da object a Foo. E questo non è possibile anche.

Ecco un lavoro su come utilizzare le dinamiche in cui il cast verrà eseguito in runtime.

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

Poi utilizzarlo come

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

Grazie. Posso scrivere la mia estensione. Speravo solo che ci fosse un modo per 'Cast', l'estensione in-build per usare il mio operatore. –

+0

@ WaterCoolerv2 Benvenuto. Ma sfortunatamente AFAIK non esiste un metodo integrato :( –

+0

Grazie. :-) Non sto ancora dicendo che dovrebbe esserci. Sto solo dicendo che lo scopo di questa domanda era: lo sto facendo da anni e anni e questo è uno dei miei animaletti e non ho mai avuto la possibilità di chiedere se potevo girare 'Cast' su obbedire al mio operatore Appare no. :-) –

Problemi correlati