Czy foreach() iteruje przez odniesienie?

Rozważ to:

List<MyClass> obj_list = get_the_list();
foreach( MyClass obj in obj_list )
{
    obj.property = 42;
}

Czy' obj ' jest odniesieniem do odpowiedniego obiektu na liście tak, że gdy zmienię właściwość, zmiana będzie trwała w instancji obiektu raz skonstruowanej gdzieś?

Author: Robert Harvey, 2009-10-08

10 answers

Tak, obj jest odniesieniem do bieżącego obiektu w kolekcji (zakładając, że MyClass jest w rzeczywistości klasą). Jeśli zmienisz jakieś właściwości za pomocą referencji, zmienisz obiekt, tak jak byś tego oczekiwał.

Należy jednak pamiętać, że nie można zmienić samej zmiennej obj, ponieważ jest to zmienna iteracyjna. Jeśli spróbujesz, pojawi się błąd kompilacji. Oznacza to, że nie można go null i jeśli iterację typów wartości, nie można modyfikować żadnych członków, jak to byłoby zmiana wartość.

Specyfikacja języka C #stwierdza (8.8.4)

" zmienna iteracji odpowiada zmienna lokalna tylko do odczytu z zakres rozciągający się nad osadzonym oświadczenie."

 57
Author: Brian Rasmussen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 21:09:42

Tak, dopóki nie zmienisz typu generycznego z List na IEnumerable..

 22
Author: jaccso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-03 16:59:25

Zadałeś tu 2 różne pytania, uporządkujmy je.

Czy pętla foreach jest powtarzana przez odniesienie?

Jeśli masz na myśli w tym samym znaczeniu co C++ dla pętli przez odniesienie, to nie. C# nie ma odniesień do zmiennych lokalnych w tym samym sensie, co C++ i dlatego nie obsługuje tego typu iteracji.

Czy zmiana zostanie utrzymana

Zakładając, że MyClass jest typem odniesienia, odpowiedź brzmi tak. Klasa jest typem odniesienia w. Net i stąd zmienna iteracji jest odniesieniem do jednej zmiennej, a nie kopią. Nie byłoby to prawdą dla typu wartości.

 18
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 14:55:54

Cóż, zdarzyło mi się, że moje zmiany nie były aktualizowane w pętli foreach, kiedy iterowałem przez kolekcję var:

var players = this.GetAllPlayers();
foreach (Player player in players)
{
    player.Position = 1;
}

Kiedy zmieniłem var na List zaczęło działać.

 14
Author: mrzepa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-10 08:32:23

Możesz w tym przypadku (używając List<T>), ale jeśli masz być iteracją nad generycznym IEnumerable<T>, to staje się ona zależna od jego implementacji.

Gdyby to było na przykład List<T> lub T[], wszystko działałoby zgodnie z oczekiwaniami. Big gotcha pojawia się, gdy pracujesz z IEnumerable<T>, który został skonstruowany przy użyciu yield. W tym przypadku nie można już modyfikować właściwości T w iteracji i oczekiwać, że będą one obecne, jeśli powtórzysz to samo IEnumerable<T> ponownie.

 5
Author: J Keegan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 12:33:51

To prawda, o ile nie jest to struktura.

 3
Author: Deepfreezed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-07 20:58:03

Cóż, bez zrozumienia, co dokładnie masz na myśli przez "iterować przez odniesienie", nie mogę odpowiedzieć dokładnie tak lub nie, ale mogę powiedzieć, że to, co dzieje się pod powierzchnią, to to, że. NET Framework konstruuje klasę "enumerator" za każdym razem, gdy kod klienta wywołuje foreach, dla życia foreach, który utrzymuje wskaźnik referencyjny do kolekcji jest iterowany, a za każdym razem, gdy foreach iterats, ir "dostarcza" jeden element i "zwiększa" wskaźnik lub odniesienie w kolekcji. wyliczenie do następnego punktu...

Dzieje się tak niezależnie od tego, czy elementy w kolekcji, nad którą iterujesz, są typami wartości czy typami referencji.

 2
Author: Charles Bretana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 14:51:07

Być może jest to dla Ciebie interesujące, aby pochylić się nad tym, że w wersji C # 7.3 można zmieniać wartości według referencji pod warunkiem, że właściwość Current wyliczenia zwróci Typ referencji. Następujące dane byłyby poprawne (dosłowna Kopia z MS docs):

Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
    item = num++;
}

Przeczytaj więcej o tej nowej funkcji na C# foreach statement | Microsoft Docs .

 1
Author: Wolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-03 13:03:34

Obj jest odniesieniem do pozycji wewnątrz listy, dlatego jeśli zmienisz jej wartość, będzie ona trwała. Teraz powinieneś się martwić o to, czy get_the_list (); robi głęboką kopię listy lub zwraca tę samą instancję.

 0
Author: Stan R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 14:57:14

Tak, dlatego też nie można zmienić enumerable object w kontekście instrukcji foreach.

 0
Author: Brian Scott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 15:15:51