2012-09-17 12 views
24

Przez bardzo długi czas był ciekawy następujące:W jaki sposób tablice implementują IList <T> bez implementowania właściwości "Count" w języku C#?

int[] array = new int[1]; 
int iArrayLength = array.Length; //1 

Ponieważ matryce realizacji IList interfejs następuje dozwolony:

int iArrayCount = ((IList<int>)array).Count; //still 1 

Ale:

int iArrayCount = array.Count; //Compile error. WHY? 
int iArrayLength = array.Length; //This is what we learned at school! 

The pytanie: W jaki sposób tablica może implementować IList<T> (szczególnie właściwość int Count { get; } z IList<T>) bez zezwolenia na użycie go w klasie bazowej?

+0

Można prawdopodobnie symulować ten sam przez shadowing „count” właściwość z klasy bazowej w swoim własnym dziedziczonej klasie, i uczynić go prywatnym zamiast. VB.NET ma do tego jawne słowo kluczowe "Cienie", nie jestem pewien co do C#, ale. –

+0

Twój tytuł jest błędny. Tablice faktycznie implementują 'Count' z [' ICollection'] (http://msdn.microsoft.com/en-us/library/system.collections.icollection.count.aspx): 'int ICollection.Count \t \t { \t \t \t dostać \t \t \t { \t \t \t \t zwrot ten.Długość; \t \t \t} \t \t} ' –

+0

@TimSchmelter ale' IList 'dziedziczy' interfejs ICollection '; 'ICollection ' również ma właściwość 'Count', więc wszystkie typy implementujące' IList 'muszą również implementować' ICollection .Count'. To prawda, właściwość nie jest zdefiniowana w 'IList ', ale pytanie jest uzasadnione. – phoog

Odpowiedz

30

ten jest znany jako wyraźnej realizacji członkiem interfejs. Element interfejsu nie jest widoczny jako element publiczny typu, ale jest dostępny przez rzutowanie odniesienia do typu interfejsu.

Można to zrobić w C# tak:

interface I 
{ 
    void M(); 
} 

class C : I 
{ 
    public int P { get; set; } 
    void I.M() { Console.WriteLine("M!"); } 
} 

Następnie można korzystać z tych typów tak:

C obj = new C(); 
obj.P = 3; 
((I)obj).M(); 

Ale nie będzie to skompilować:

obj.M(); 

Jak zauważa JeffN825, jednym z powodów, dla których oczywiste jest to, że członkowie interfejsu są eksplikowane, jest to, że nie są one obsługiwane przez typ. Na przykład Add zgłasza wyjątek (relevant discussion). Innym powodem, dla którego explicite jest członkostwo, jest duplikowanie innego członka publicznego o innej nazwie. To jest powód, dla którego Count jest implementowany jawnie; odpowiedni członek publiczny to Length.. Wreszcie, niektórzy członkowie są implementowani niejawnie, a mianowicie indeksator. Obie te linie działać (zakładając arr jest tablicą int):

arr[0] = 8; 
((IList<int>)arr)[0] = 8; 
+0

"wyraźna definicja członka interfejsu" dobre słowo kluczowe dla google! Nie wiedziałem o tym, dzięki! To ciekawe, że nie ma żadnego modyfikatora dostępu. Dzięki temu możesz korzystać z wewnętrznych interfejsów na publicznych klasach bez konieczności implementowania wszystkich metod/właściwości jako publicznych, miłych! – Gerrit

+0

@ Gerrit; właściwie to jest nieprawidłowe. Powinna to być "implementacja jawnego interfejsu użytkownika". Poprawiłem. – phoog

+0

@ Gerrit Eric Lippert ma interesującą dyskusję na temat używania wewnętrznych interfejsów na typach publicznych tutaj: http://blogs.msdn.com/b/ericlippert/archive/2011/12/08/so-many-interfaces-part-two. aspx – phoog

11

Ponieważ tablica nie obsługuje wszystkich funkcji IList (Add/Remove/etc), IList.Count (i kilka innych metod) są zaimplementowane prywatnie (jawnie). Można to zobaczyć w demontażu:

int ICollection.Count 

Jeśli naprawdę chciał wykorzystać Hrabiego, można zrobić

((IList)myArray).Count 
Powiązane problemy