Неожиданный результат при циклическом просмотре List<Action>

В настоящее время я ищу каверзные фрагменты интервью, и я нашел два, которые я не могу объяснить. Я объединил их вместе, чтобы их можно было запускать одновременно.

Вот код:

using System.Collections.Generic;
public class Program
{
    public static void Main(string[] args)
    {
        var intActions = new List<Action>();
        for (int i = 0; i < 4; i++)
            intActions.Add(() => { Console.WriteLine(i); });

        foreach (var action in intActions)
            action();


        string[] strings = { "abc", "def", "ghi" };
        var stringActions = new List<Action>();
        foreach (string str in strings)
            stringActions.Add(() => { Console.WriteLine(str); });

        foreach (var action in stringActions)
            action();
    }
}

Результат:

4
4
4
4
abc
def
ghi

Может ли кто-нибудь объяснить мне, почему такой результат? Я бы ожидал четыре "4" с четырьмя "ghi" или "0123" и "abc def ghi"

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
32
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой вы видите 4444, а не 0123, и ghi ghi ghi вместо abc def ghi, связана с закрытия.

Переменная i, переданная делегату, передается Справка, а не ценность, что означает, что все действия будут указывать на одну и ту же ячейку памяти для переменной i и последнее значение для i (установлено на 4 на последней итерации цикла) .

Чтобы вывод был 0123, копирование переменной в другую временную переменную будет означать, что каждое действие будет иметь указатель на отдельную ячейку памяти и, таким образом, даст числа как «ожидаемые».

var intActions = new List<Action>();
for (int i = 0; i < 4; i++) {
    int copy = i;
    intActions.Add(() => { Console.WriteLine(copy); });
}

foreach (var action in intActions)
    action();

То же самое относится и ко второй части вашего примера:

string[] strings = { "abc", "def", "ghi" };
var stringActions = new List<Action>();
foreach (string str in strings) {
    var copy = str;
    stringActions.Add(() => { Console.WriteLine(copy); });
}

foreach (var action in stringActions)
    action();

Это относится только к действиям или происходит то же самое, если я передаю свою переменную типа значения обычному CW? Когда он запускается, CW получает ссылку на переменную И копирует ее, ЗАТЕМ запускает тело?

Behold The Light 09.04.2022 14:47

@BeholdTheLight Что такое CW? Попробуйте и узнаете в любом случае.

Ermiya Eskandary 09.04.2022 14:48

Я просто хотел сделать Console.WriteLine немного короче. Btw, спасибо за объяснение.

Behold The Light 09.04.2022 14:52

О, CW — это консольная строка записи! Это относится только к делегату, вы можете просто сделать Console.WriteLine переменной вне действия, и она будет работать, как и ожидалось.

Ermiya Eskandary 09.04.2022 14:55

Другие вопросы по теме