Domanda

Tutto eredita dall'oggetto. È la base dell'eredità. Tutto può implicitamente ricoprire l'albero ereditario, cioè.

object me = new Person();

Pertanto, seguendo questo fino alla sua logica conclusione, un gruppo di Persone sarebbe anche un gruppo di oggetti:

List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.

Tranne il fatto che non funzionerà, le persone che hanno progettato .NET o hanno ignorato questo, o c'è un motivo, e non sono sicuro di quale. Almeno una volta mi sono imbattuto in una situazione in cui ciò sarebbe stato utile, ma ho dovuto finire per usare un brutto hack (sottoclasse Elenco solo per implementare un operatore cast).

La domanda è questa: c'è una ragione per questo comportamento? Esiste una soluzione più semplice per ottenere il comportamento desiderato?

Per la cronaca, credo che la situazione in cui desideravo questo tipo di comportamento fosse una funzione di stampa generica che mostrava elenchi di oggetti chiamando ToString () e formattando le stringhe in modo corretto.

È stato utile?

Soluzione

OK, tutti coloro che hanno usato generics in .net devono essersi imbattuti in questo in un punto o nell'altro.

Sì, intuitivamente dovrebbe funzionare. No, nella versione corrente del compilatore C # non funziona.

Eric Lippert ha una spiegazione davvero valida di questo problema (è in undici parti o qualcosa del genere e ti farà piegare la mente in alcuni punti, ma vale la pena leggerlo). Vedi qui .

modifica:

ha estratto un altro collegamento pertinente, questo discute come java gestisce questo. Vedi qui

Altri suggerimenti

puoi usare linq per lanciarlo:

IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()

A prima vista, questo non ha senso intuitivo. Ma lo fa. Guarda questo codice:

List<Person> people = new List<Person>();
List<object> things = people; // this is not allowed
// ...
Mouse gerald = new Mouse();
things.add(gerald);

Ora abbiamo improvvisamente un List di Person oggetti ... con un Mouse al suo interno!

Questo spiega perché non è consentita l'assegnazione di un oggetto di tipo A<T> a una variabile di tipo A<S>, anche se S è un supertipo di T.

La soluzione alternativa a linq è buona. Un'altra soluzione alternativa, poiché si utilizza l'oggetto tipo, è passare l'elenco come IEnumerable (non la versione generica).

Modifica : C # 4 (attualmente beta) supporta un parametro di tipo covariante in IEnumerable. Anche se non sarai in grado di assegnare direttamente a un Elenco & Lt; oggetto & Gt; ma puoi passare la tua lista a un metodo aspettandoti un IEnumerable & Lt; oggetto & Gt;.

Mentre quello che stai cercando di fare scorre davvero logicamente, in realtà è una funzionalità che molte lingue non supportano in modo nativo. Questo si chiama co / contro-varianza, che ha a che fare con quando e come gli oggetti possono essere implicitamente lanciati da una cosa all'altra da un compilatore. Per fortuna, C # 4.0 porterà covarianza e contraddizione nell'arena C # e tali cast impliciti come questo dovrebbero essere possibili.

Per una spiegazione dettagliata di ciò, il seguente video di Channel9 dovrebbe essere utile:

http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/

Con i metodi di estensione linq puoi farlo

IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();

In caso contrario, poiché si sta digitando fortemente l'elenco, la conversione implicita non è consentita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top