Я обнаружил, что методам итератора в типах значений разрешено изменять 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
Почему это не ошибка компилятора (или хотя бы предупреждение), чтобы изменить структуру в итераторе?
Такое поведение - тонкая ловушка, которую нелегко понять.
Анонимные методы, которые имеют то же ограничение, не могут использовать это
вообще .
Примечание: изменчивые структуры - зло ; это никогда не должно происходить на практике.