Czy mogę użyć yield return
, gdy typem zwrotu jest IGrouping<TKey, TElement>
lub IDictionary<TKey, TValue>
?zwrot plonów działa tylko dla IEnumerable <T>?
Odpowiedz
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.
Poręczny artykuł tutaj http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx jeśli chcesz zaimplementować IEnumerable siebie. – Rory
@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. –
Zgadzam się, chociaż w niektórych przypadkach IGrouping może być przyjemniejszy, wydaje się, że łatwiej jest użyć IEnumerable
Nie, po prostu IEnumerable :-)
Nieprawdziwe; zobacz moją odpowiedź ;-p –
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.
Zamiast tego wyświetla się specyfikacja językowa ... zobacz 8.18 w ECMA 334 –
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.
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.
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. –
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:
- Realizuje
IEnumerator
iIEnumerator<T>
gdzieT
jest typu wydajność iteracyjnej.
[...]
Z §10.14.5:
wyliczalnych obiekt ma następujące właściwości:
- to realizuje
IEnumerable
iIEnumerable<T>
, gdzieT
jest typem wydajność iteracyjnej.
[...]
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.
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.
Jesteś "uzyskując listę całych Słowniki, a nie pary klucz-wartość. – titol
możliwy duplikat [Niektóre pomagają zrozumieć "wydajność"] (http://stackoverflow.com/questions/317462/some-help-understanding-yield) – nawfal