Почему итераторы в структурах могут изменять это?

Я обнаружил, что методам итератора в типах значений разрешено изменять this .
Однако из-за ограничений среды CLR изменения не видны вызывающему методу. ( this передается по значению)

Таким образом, одинаковый код в итераторе и неитераторе дает разные результаты:

static void Main() {
    Mutable m1 = new Mutable();
    m1.MutateWrong().ToArray();     //Force the iterator to execute
    Console.WriteLine("After MutateWrong(): " + m1.Value);

    Console.WriteLine();

    Mutable m2 = new Mutable();
    m2.MutateRight();
    Console.WriteLine("After MutateRight(): " + m2.Value);
}

struct Mutable {
    public int Value;

    public IEnumerable MutateWrong() {
        Value = 7;
        Console.WriteLine("Inside MutateWrong(): " + Value);
        yield break;
    }
    public IEnumerable MutateRight() {
        Value = 7;
        Console.WriteLine("Inside MutateRight(): " + Value);
        return new int[0];
    }
}

Вывод:

Inside MutateWrong(): 7
After MutateWrong(): 0

Inside MutateRight(): 7
After MutateRight(): 7

Почему это не ошибка компилятора (или хотя бы предупреждение), чтобы изменить структуру в итераторе?
Такое поведение - тонкая ловушка, которую нелегко понять.

Анонимные методы, которые имеют то же ограничение, не могут использовать это вообще .

Примечание: изменчивые структуры - зло ; это никогда не должно происходить на практике.

11
задан Community 23 May 2017 в 12:02
поделиться