2012-01-06 17 views
26

Próbuję napisać własną (prostą) implementację List. To, co zrobiłem do tej pory:Problemy implementujące IEnumerable <T>

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace provaIEnum 
{ 
    class MyList<T> : IEnumerable<T> 
    { 
     private T[] _array; 
     public int Count { get; private set; } 

     public MyList() { /* ... */ } 
     public void Add(T element) { /* ... */ } 

     // ... 

     public IEnumerator<T> GetEnumerator() 
     { 
      for (int i = 0; i < Count; i++) 
       yield return _array[i]; 
     } 
    } 

Dostaję błąd o GetEnumerator jednak:

„provaIEnum.Lista” nie wprowadzania elementu interfejsu „System.Collections.IEnumerable.GetEnumerator() ". 'provaIEnum.Lista.GetEnumerator()' nie może zaimplementować 'System.Collections.IEnumerable.GetEnumerator()', ponieważ nie ma ona zgodnego typu zwrotu "System.Collections.IEnumerator".

Nie jestem pewien, czy rozumiem, co VS próbuje mi powiedzieć i nie mam pojęcia, jak to naprawić.

Dzięki za poświęcony czas

+0

Pamiętaj, że nie powinieneś pisać swojego modułu wyliczającego, ponieważ obecnie możesz modyfikować swoją wewnętrzną tablicę w 'foreach' (wywołanie' Add' w foreach nie spowoduje wyjątku). [Zobacz] (http://stackoverflow.com/questions/24142614/when- mógłby-i-separately-implement-ienumeratort) – nawfal

+0

@Nawfal dobry punkt, błędy zawsze nas obserwują;) – BlackBear

Odpowiedz

41

Od IEnumerable<T> narzędzia IEnumerable trzeba zaimplementować ten interfejs, jak również w swojej klasie, który ma nierodzajową wersję metody GetEnumerator. Aby uniknąć konfliktów można go wdrożyć wyraźnie:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    // call the generic version of the method 
    return this.GetEnumerator(); 
} 

public IEnumerator<T> GetEnumerator() 
{ 
    for (int i = 0; i < Count; i++) 
     yield return _array[i]; 
} 
+1

Dziękuję, nie wiedziałem IEnumerable implementuje IEnumerable (choć brzmi to wyraźnie: P) – BlackBear

+5

Ponieważ nie jawnie zakwalifikowano 'IEnumerator' i' IEnumerable.GetEnumerator' z 'System.Collections. ', To się nie powiedzie, jeśli nie masz' using System.Collections' , mówiąc (dość niepomyślnie), że 'IEnumerator' potrzebuje ogólnego argumentu! – PJTraill

10

Musisz wdrożyć nierodzajową metodę GetEnumerator również:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    return GetEnumerator(); 
} 

Ponieważ interfejs IEnumerable<T> rozciąga IEnumerable, trzeba wdrożyć metody zadeklarowane na obu.

+0

Jawne implementacje interfejsu nie mogą mieć modyfikatora dostępu – Nuffin

36

Przeczytaj uważniej komunikat o błędzie; mówi dokładnie, co musisz zrobić. Nie wdrożyłeś System.Collections.IEnumerable.GetEnumerator.

Po wdrożeniu generatora IEnumerable<T> należy również wykonać moduł do generowania System.Collections.IEnumerable.

Standardowym sposobem na to jest:

public IEnumerator<T> GetEnumerator() { whatever } 
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
{ 
    return this.GetEnumerator(); 
} 
+0

+1 dla "standardowego sposobu", ucz się każdego dnia :) – BlackBear

4

Dodaj następujące metody:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    return this.GetEnumerator(); 
} 
2

Istnieją dwa przeciążenia GetEnumerator() że trzeba wdrożyć. Jedna pochodzi z IEnumerable<T> i zwraca IEnumerator<T>. Druga pochodzi z IEnumerable i zwraca IEnumerator. Nadpisanie powinna wyglądać następująco:

IEnumerator IEnumerable.GetEnumerator()

To dlatego IEnumerable<T> realizuje IEnumerable.

1

Od swojej klasie, MyList<T> dziedziczy IEnumerable<out T> który z kolei dziedziczy nierodzajową IEnumerable, masz dwie metody należy wdrożyć:

IEnumerator<T> IEnumerable<T>.GetEnumerator() 
     { 
      throw new NotImplementedException(); 
     } 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      throw new NotImplementedException(); 
     } 

Łatwym sposobem na to jest, kiedy zadeklarować swoją klasę:

class MyList<T> : IEnumerable<T> 

kliknij prawym przyciskiem myszy i wybierz tekst IEnumerable<T>Wdrożenie interfejsu> Wdrożenie interfejsu explictly z menu kontekstowego.

0

Mam podobny problem, chociaż zaimplementowałem również IEnumerable i IEnumerable. Używałem typu niestandardowego (klasy Person) niż typ ogólny T. Powód był taki, że przestrzeń nazw nie została uwzględniona w górnej części pliku.

using System.Collections; 

Po dodaniu przestrzeni nazw było to dla mnie w porządku.

Powiązane problemy