2009-07-01 3 views

Odpowiedz

36

yield return prace dokładnie 4 przypadkach:

  • IEnumerable
  • IEnumerable<T>
  • IEnumerator
  • IEnumerator<T>

To dlatego, że musi zbudować maszynę państwową wewnętrznie; słownik (itp.) nie byłby z tym możliwy. Możesz oczywiście tylko return odpowiedni typ.

+0

Poręczny artykuł tutaj http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx jeśli chcesz zaimplementować IEnumerable siebie. – Rory

+0

@Rory tak, sama implementacja to ogromna PITA i nie mogę wymyślić żadnych "normalnych" powodów, aby kiedykolwiek to zrobić, teraz, gdy istnieją bloki iteracyjne. Mam kilka takich, ale zazwyczaj jest to zgodne z projektami, które muszą być budowane nawet na kompilatorach C# 1.2; niezupełnie "normalny" scenariusz. –

+0

Zgadzam się, chociaż w niektórych przypadkach IGrouping może być przyjemniejszy, wydaje się, że łatwiej jest użyć IEnumerable >, więc otrzymasz magię zwrotu plonów. – Rory

0

Nie, po prostu IEnumerable :-)

+0

Nieprawdziwe; zobacz moją odpowiedź ;-p –

1

Nie sądzę. Chociaż documentation nie dokładnie to określa, sposób jego opisu oznacza, że ​​może on być użyty tylko wtedy, gdy typ powrotu metody jest albo IEnumerable lub IEnumerable<T>. Być może będziesz w stanie napisać klasę, która implementuje IGrouping z danymi IEnumerable (która zostanie zwrócona z Twojej metody przy użyciu yield return), ale to naprawdę jedyna opcja.

+1

Zamiast tego wyświetla się specyfikacja językowa ... zobacz 8.18 w ECMA 334 –

2

Nie, ponieważ blok iteratora jest po prostu maszyną stanów zbudowaną w twoim imieniu przez kompilator. Ta funkcja umożliwia "uzyskanie" i element jako część sekwencji.

Jeśli zwracany typ był inny niżna przykład), kompilator musiałby wygenerować metody implementacji tego interfejsu iw tym momencie nie miałoby to większego sensu, ponieważ pracowałbyś raczej z kolekcją niż sekwencja.

15

Można jednak zwrócić IEnumerable<KeyValuePair<K,V>>, który będzie podobny do słownika. Następnie wydasz zwrot KeyValuePairs. Można nawet owinąć to inną metodą, która tworzy słownik po powrocie. Jedyną rzeczą, której pierwsza metoda nie gwarantowałaby, jest wyjątkowość kluczy.

+7

Następnie tracisz czas dostępu O (1) i musisz przechodzić przez każdy KVP, aby znaleźć właściwy klucz, biorąc pod uwagę najgorsze O (n) razy. –

4

Odpowiedź: Nr A yield return Oświadczenie może być stosowane tylko wówczas, gdy typ zwracany jest IEnumerator, IEnumerator<T>, IEnumerable lub IEnumerable<T>.

Z §8.14 z C# 3.0 spec:

Stwierdzenie wydajność jest stosowane w bloku iteracyjnej (§8.2) w celu uzyskania wartości dla przedmiotu enumeratora (§10.14.4) lub wyliczalnych przedmiot (§10.14.5) iteratora lub sygnalizowania końca iteracji.

Z §10.14.4:

Numerator obiekt ma następujące właściwości:

  1. Realizuje IEnumerator i IEnumerator<T> gdzie T jest typu wydajność iteracyjnej.

[...]

Z §10.14.5:

wyliczalnych obiekt ma następujące właściwości:

  1. to realizuje IEnumerable i IEnumerable<T>, gdzie T jest typem wydajność iteracyjnej.

[...]

2

Wystarczy zadzwonić metody iteracyjnej i łańcuch ToDictionary lub GroupBy po nim, a masz dużo to samo. Umieść to w jednoliniowej metodzie wrappera, jeśli chcesz wywołać to w ten sposób z kilku miejsc.

-2

Jako że yield return może być używany z typami jako IEnumerator<T>, dlaczego nie zrobić czegoś takiego?

internal static IEnumerable<Dictionary<byte, string>> GetData() 
    { 
     Dictionary<byte, string> result = GetMyData(); //read from db 
     yield return result; 
    } 

Mam nadzieję, że to pomaga.

+0

Jesteś "uzyskując listę całych Słowniki, a nie pary klucz-wartość. – titol