2013-11-22 5 views
5

Dies ist etwas, das ich festgestellt, während der C# IList Sammlungen mitObjektzuordnung in C#

IList<MyClass> foo = new List<MyClass>(); 
var bar = new List<MyClass>(); 

foo.AddRange() // doesn't compile 
bar.AddRange() // compile 

Soweit ich weiß, in C# (im Gegenteil von C++), wenn wir ein Objekt mit dieser Syntax zu erstellen, die Objekttyp erhält die rechte Seite (Zuweisung) und nicht die linke (Deklaration).

Vermisse ich etwas hier!

EDIT

ich es immer noch nicht erhalten, auch nachdem Sie Ihre Antworten, foo und bar die gleiche Art haben! enter image description here

+2

"var" ist vom Typ Liste , die die Methode "AddRange" hat, während foo vom Typ IList ist, die eine Schnittstelle ist, die nicht über die "AddRange" -Methode verfügt. – sjkm

+0

Aber beide werden instanziiert mit dem Typ Liste

+0

@Schneider Das ist wahr, aber aus Sicht des Compilers ist 'foo' vom Typ' IList <> 'nicht' List <> ' – rhughes

Antwort

18

Es gibt nichts so subtil geht hier vor:

  • foo hat den Typ IList<MyClass> und IList<T> keine AddRange Methode haben
  • bar den Typ hat List<MyClass> und List<T> eine AddRange Methode hat.

Das ist alles. In C++ wäre es genauso.

Update: In der Bearbeitung-zusätzlich rufen Sie GetType(), die den Laufzeittyp des Objekts erhält - zur Kompilierzeit sucht der Compiler den statischen Typ der foo und bar Variablen.

Nachdenken über Object myObj = "MyString" könnten die Dinge klarer machen, weil es ein deutlicher Unterschied zwischen einem ‚Objekt‘ und ein ‚String‘, auch wenn sie die gleiche Vererbungsbeziehung wie IList haben und Liste

+0

Meine Änderungen anzeigen ... –

8

Das Problem ist, dass Sie die Schnittstelle und IList nicht verwenden AddRange hat aber List hat AddRange

Wenn Sie es

List<MyClass> foo = new List<MyClass>(); 

es funktionieren wird sich ändern. wie es diese Methode hat. Hier

ist, was IList hat

Sie auch

IEnumerable<MyClass> foo = new List<MyClass>(); 

tun können, und Sie werden feststellen, dass dies schränkt es noch

EDIT FÜR IHRE EDIT:

Sie werden beide Seien Sie der gleiche Typ, da beide immer noch Lists sind. Der Unterschied kommt mit der Variablen, die Sie verwenden. Wenn Sie die Schnittstelle verwenden, begrenzen Sie die Operationen auf diejenigen, die die Schnittstelle unterstützt. Als List implementiert IList, IList hat eine Teilmenge der Operationen, die List hat.

Das zugrunde liegende Objekt ist immer noch eine List.

+0

Meine Änderungen anzeigen ... –

+0

@Schneider Siehe aktualisierte Antwort –

2

Der zugrunde liegende Typ von foo ist List, aber sein statischer Typ, den der Compiler verwendet, um die Korrektheit sicherzustellen, lautet IList<T>. Alles, was Sie unter foo aufrufen, muss als Teil des Typs IList<T> deklariert werden.

0

Ich habe Ihre Frage nicht verstanden, aber in dieser Situation verhalten sich C# und C++ genauso. dass schaffen, in Ihrem Beispiel, dass der Code würde Sie

IList<MyClass> foo = new List<MyClass>(); 
var bar = new List<MyClass>(); 

((List<MyClass>)foo).AddRange(); 
bar.AddRange() // compile 

In der Tat schreiben können kompiliert wird es hat den gleichen Sinn wie dynamic_cast in C++.

0

Wie alle genannten IList unterstützt AddRange nicht und es muss nicht unterstützt werden.

Sie können:

1) ((List<MyClass>)foo).AddRange(anotherList); 
2) You can also use extension method to AddRange 
3) There are another workarounds for this problem e.g. Concat etc. 

Ich denke auch, die Schnittstelle ist nicht jede Funktion auf die Klasse an einem bestimmten Punkt unterstützen müssen Sie Abstraktion und das soll auf Interface Segregation Prinzip basieren.