3 Stimmen

Logik und ihre Anwendung auf Collections.Generic und Vererbung

Alles erbt von object. Das ist die Grundlage der Vererbung. Alles kann implizit in den Vererbungsbaum aufgenommen werden, d.h..

object me = new Person();

Folgt man der logischen Schlussfolgerung, so ist eine Gruppe von Menschen auch eine Gruppe von Objekten:

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

Nur funktioniert das nicht. Die Leute, die .NET entwickelt haben, haben das entweder übersehen, oder es gibt einen Grund dafür, und ich bin mir nicht sicher, welchen. Zumindest einmal bin ich in eine Situation geraten, in der dies nützlich gewesen wäre, aber ich musste am Ende einen fiesen Hack verwenden (Unterklassifizierung von List, nur um einen Cast-Operator zu implementieren).

Die Frage ist nun: Gibt es einen Grund für dieses Verhalten? Gibt es eine einfachere Lösung, um das gewünschte Verhalten zu erreichen?

Für das Protokoll, ich glaube, die Situation, dass ich diese Art von Verhalten wollte, war eine allgemeine Druckfunktion, die Listen von Objekten durch den Aufruf ToString() und die Formatierung der Zeichenfolgen schön angezeigt.

5voto

Hamish Smith Punkte 8011

OK, jeder, der Generika in .net verwendet hat, muss irgendwann einmal auf dieses Problem gestoßen sein.

Ja, intuitiv sollte es funktionieren. Nein, in der aktuellen Version des C#-Compilers funktioniert es nicht.

Eric Lippert hat eine wirklich gute Erklärung zu diesem Thema (sie besteht aus elf Teilen oder so und wird Ihnen stellenweise den Kopf verdrehen, aber es lohnt sich, sie zu lesen). Siehe aquí .

editar:

einen anderen relevanten Link ausgegraben, der beschreibt, wie Java damit umgeht. Siehe aquí

4voto

mattlant Punkte 15146

Können Sie Linq verwenden, um es zu casten:

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

0 Stimmen

Beachten Sie, dass es sich hierbei um einen iterativen Cast handelt, der zu Leistungseinbußen führen wird. Verwechseln Sie die LINQ Cast<T>-Methode nicht mit einem nativen C#-Cast...die beiden sind unterschiedlich.

3voto

Thomas Punkte 160390

Auf den ersten Blick ergibt dies keinen intuitiven Sinn. Aber es ist so. Sehen Sie sich diesen Code an:

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

Jetzt haben wir plötzlich eine List de Person Objekte... mit einer Mouse in ihm!

Dies erklärt, warum die Zuweisung eines Objekts vom Typ A<T> auf eine Variable des Typs A<S> ist nicht erlaubt, auch wenn S ist ein Supertyp von T .

0 Stimmen

Einverstanden, aber wäre es nicht schön, die gleichen Möglichkeiten wie in der Java-Generik zu haben, wo Sie 'T ? super MyClass' angeben können?

0 Stimmen

Sie könnten dieses Problem immer umgehen, indem Sie die gecastete Liste als schreibgeschützt kennzeichnen, aber Ihr Punkt ist gut getroffen.

0 Stimmen

Versuchen Sie dann die Erklärung von Eric Lippert, die in der Angenommenen Antwort erwähnt wird. Sie geht auf alle Details ein.

3voto

dcstraw Punkte 3133

Die Linq-Umgehung ist ein guter Ansatz. Ein weiterer Workaround, da Sie Typ Objekt verwenden, ist die Liste als IEnumerable (nicht die generische Version) zu übergeben.

Editar : C# 4 (currently beta) supports a covariant type parameter in IEnumerable. Während Sie nicht in der Lage sein werden, direkt einer List<object> zuzuweisen, können Sie Ihre Liste an eine Methode übergeben, die eine IEnumerable<object> erwartet.

2voto

jrista Punkte 31522

Während das, was Sie versuchen, in der Tat logisch fließen, ist es eigentlich eine Funktion, die viele Sprachen nicht nativ unterstützen. Dies ist, was genannt co/contra Varianz, die zu tun hat mit, wann und wie Objekte können implizit von einer Sache zu einem anderen durch einen Compiler gecastet werden. Glücklicherweise wird C# 4.0 Kovarianz und Kontravarianz in die C#-Arena bringen, und solche impliziten Casts wie diese sollten möglich sein.

Eine ausführliche Erklärung hierzu finden Sie im folgenden Video von Channel9:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X