2010-01-28 22 views
5

Supponiamo di avere la seguente classe:Passando una collezione Interface

class Car : IPainting 
{ 
... 
} 

Poi una funzione come questa:

void AddCars(IEnumerable<Car> collection) 

Poi un frammento di codice come questo:

Car bmw = new Car(); 
Car mercedes = new Car(); 

IPainting a = (IPainting) bmw; 
IPainting b = (IPainting) mercedes; 

IPainting[] paintings = new IPainting[] {a, b}; 

AddCars(paintings); // fails to compile 

Questo, Naturalmente non viene compilato perché il metodo AddCars() accetta solo una raccolta di Cars ma è ciò che è costituito dall'array 'paintings'.

So che C# 4.0 probabilmente fornirà una soluzione per questo. C'è qualche soluzione per oggi?

Grazie,

Alberto

+1

C# 4.0 non fornirà un soluzione per il codice che hai qui. Non sarai mai in grado di passare qualcosa di un tipo che è più alto nell'ereditarietà raglia a un metodo che si aspetta qualcosa di più basso. Come altri hanno sottolineato, il tuo metodo dovrebbe prendere in considerazione IPainting - non Car per farlo funzionare. –

risposta

3

C# 4 non consentirà il codice che hai scritto, in quanto il metodo AddCars si aspetta un IEnumerable<Car> che implementa IPainting. Questo non significa che sia possibile passare alla classe (si potrebbe ad esempio avere un class Bike : IPainting che non ha nulla a che fare con la classe Car. Tuttavia, consentirà il contrario, se si dispone di void AddCars(IEnumerable<IPainting> collection) è possibile passare un List<Car> al metodo.

Fino ad allora, sarà necessario attenersi a passare Car sequenze al metodo, utilizzando un meccanismo di fusione (come painting.Cast<Car>() suggerito in altre risposte).

+0

I dipinti.Cast () in qualche modo più veloce di un ciclo for che esegue il cast di ogni oggetto sul tipo Car? Grazie. – abenci

+0

@devdept: non posso dire; mai fatto alcun confronto di prestazioni su questo. Sarei sorpreso se non fosse abbastanza veloce per la maggior parte degli scenari del mondo reale. –

4

ne dite di usare Linq: AddCars(paintings.Cast<Car>());

+0

Non usiamo Linq. Non usiamo affatto i database. Dove posso leggere di più sull'approccio che hai suggerito? – abenci

+3

@devdept - che è linq per gli oggetti, non da linq a sql. Ha _nothing_ da fare con i database. –

7

provare a utilizzare un metodo generico:

void AddCars<T>(IEnumerable<T> collection) where T : IPainting 
+0

Questa soluzione consentirà di trasmettere gli array Car [] e IPainting [] a AddCars()? – abenci

+0

sì, lo permetterebbe. –

4

Il codice è fondamentalmente errata. La tua classe garantisce che tutte le auto implementino IPainting, ma non c'è alcuna garanzia che tutte le macchine IPainting siano auto.

Probabilmente potresti farlo funzionare con un casting, ma penso che dovresti riconsiderare il tuo design.

AddCars(new Car[] { bmw, mercedes }); 
+0

Hai ragione, ma so che è sempre vero. C'è un modo per far rispettare questo? Con un singolo oggetto Car posso facilmente trasmetterlo a IPainting, il problema è che non posso fare lo stesso per le collezioni. – abenci

Problemi correlati