Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Akkor válasszon iterátort, ha olyan sorozatot szeretne visszaadni, amelynek elemeit a hívók egyenként használhatják fel anélkül, hogy a teljes eredményt egy gyűjteménybe építenék. Ez a megközelítés jól használható generált értékek esetén, az egyéni vezérlési folyamattal rendelkező szűrőkhöz, valamint azokhoz a sorozatokhoz, amelyek olvasását a hívók idő előtt abbahagyhatják. A befejezett gyűjteményhez képest az iterátor megváltoztatja, hogy mikor történik a munka, nem csak azt, ahogyan megírja.
Tip
Ez a cikk ismerteti a szinkron iterátorokat a metódusokat, hurkokat és gyűjteményeket ismerő fejlesztőknek. A teljes yield szintaxist és korlátozásokat lásd az yieldutasításreferenciát.
Az iterátormetódus egyenként egymás után állítja elő az értékek sorozatát. Ez a cikk azokat az iterátormetódusokat ismerteti, amelyek IEnumerable<T> értéket adnak vissza, és amelyek értékeit a hívók általában egy foreach utasítással használják fel.
Elemek létrehozása a(z) yield return elemmel
A sorozat következő elemének megadására szolgál yield return . Az alábbi iterátor egy érzékelő elfogadható hőmérséklet-értékeit választja ki. Ebben a forgatókönyvben -1 az érzékelő adatainak végét jelöli.
int[] readings = [21, 27, 24, -1, 19];
IEnumerable<int> acceptedReadings =
SelectTemperatures(readings, maximum: 25);
Console.WriteLine("Sequence created.");
foreach (int temperature in acceptedReadings)
{
Console.WriteLine($"Accepted: {temperature}°C");
}
static IEnumerable<int> SelectTemperatures(
IEnumerable<int> readings,
int maximum)
{
foreach (int reading in readings)
{
Console.WriteLine($"Checking {reading}°C");
if (reading == -1)
{
yield break;
}
if (reading <= maximum)
{
yield return reading;
}
}
}
SelectTemperatures a(z) IEnumerable<int> értéket adja vissza, amely int értékek sorozatát jelöli. Mindegyik yield return reading egy értéket biztosít a foreach hurok számára. Miután a hívó kezeli ezt az értéket, az iterátor a következő bemenettel folytatódik.
Használja az általános IEnumerable<T> formát a legtöbb modern C#-kódhoz. A típusargumentum ( például int) jelzi a hívóknak, hogy a sorozat melyik elemtípust tartalmazza.
A sorozat befejezése a következővel: yield break
Egy iterátor lezárásához használja a yield break elemet, mielőtt a vezérlés eléri a metódus végét. A példában a sentinel érték -1 azt jelenti, hogy nincs több mérési érték:
if (reading == -1)
{
yield break;
}
Az iterátor természetesen véget is ér, amikor a végrehajtás eléri a törzse végét. Használja a yield break elemet, ha egy feltételnek azonnal le kell állítania az elemgyártást.
Iterátor bejárása foreach
Az iterátor ugyanolyan IEnumerable<T> szerkezetet tesz elérhetővé, mint sok .NET-gyűjtemény. A hívók anélkül használhatják foreach , hogy tudnák, hogyan állítja elő a sorozat az elemeit:
foreach (int temperature in SelectTemperatures(readings, 25))
{
Console.WriteLine($"Accepted: {temperature}°C");
}
A meghívó kód minden elemet lekér, ahogy a hurok előrehalad. Az iterátor megtartja a kérések közötti pozícióját, és az előző yield returnután is folytatódik .
A késleltetett elemek előállításának megértése
Az iterátor metódus meghívása nem futtatja azonnal a törzsét. A metódus akkor kezd elemeket létrehozni, amikor a hívó elkezdi az enumerálást. Ezt a viselkedést halasztott végrehajtásnak nevezzük.
A példa minden Checking ... üzenet előtt kiírja a Sequence created. elemet. Az iterátor csak akkor kezdi el ellenőrizni az olvasatokat, amikor a foreach hurok az első elemet kéri.
A halasztott végrehajtás gyakorlati hatással bír:
- A hívó elkezdheti a feldolgozást, mielőtt az iterátor az összes elemet visszaadná.
- Az iterátor korán
yield breakleállhat. - Az a hívó, amely soha nem járja be a sorozatot, nem futtatja az iterátor törzsét.
- Minden új enumerálás újra futtatja az iterátort.
Tedd egyértelművé a késleltetett végrehajtást a metódus céljában és dokumentációjában. Az olvasók önmagában a IEnumerable<T> alapján nem tudnak következtetni a végrehajtás időzítésére, mert az iterátorok és a kollekciók is megvalósíthatják ezt az interfészt. Az elemgyártás legyen mentes a nem kapcsolódó mellékhatásoktól, mert a hívók később vagy többször is bejárhatják a sorozatot. A példa diagnosztikai üzenetei ezt az időzítést szemléltetik.
Iterátor vagy gyűjtemény kiválasztása
Iterátort ad vissza, ha az értékek természetesen egyenként érkeznek, vagy ha a hívónak nincs szüksége azonnal a teljes eredményre. Teljes gyűjteményt ad vissza, ha a hívóknak stabil pillanatképre, indexelt hozzáférésre vagy ismételt bejárásra van szükségük az elemek újraszámítása nélkül.
Mindkét módszer ugyanazokat az elemeket tudja visszaadni. Az iterátor az elemek előállítását a hívó felügyelete alatt hagyja; a gyűjteményt összeállító metódus még a visszatérése előtt befejezi ezt a munkát.
Akkor használjon szokásos hurkot, ha minden elemnél műveletet szeretne végrehajtani anélkül, hogy sorozatot adna vissza. Standard szűrő vagy átalakítás esetén előnyben részesítse a LINQ-műveletet, például Where vagy Select; írjon iterátort, ha az egyéni elemelőállítási logika egyértelműbb utasítássorozatként.
Az iterátor metódusok együtt használhatók a LINQ-val, mert mindkettő a(z) IEnumerable<T>-t használja. Egy hívó például hozzáadhat egy másik szűrőt:
var comfortableReadings = SelectTemperatures(readings, 25)
.Where(static temperature => temperature >= 18);
Az iterátor és a LINQ művelet halasztva marad, amíg a kód fel nem sorolja a(z) comfortableReadings elemet.
Az aszinkron szekvenciákról az aszinkron streamek létrehozása és felhasználása című témakörben olvashat. Az egyéni számbavételi mintákhoz és az összes yield korlátozáshoz használja a nyelvi referenciát.