gpt4 book ai didi

c# - 为什么结构中的迭代器可以修改这个?

转载 作者:可可西里 更新时间:2023-11-01 08:48:28 26 4
gpt4 key购买 nike

I discovered that iterator methods in value types are allowed to modify 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<int> MutateWrong() {
Value = 7;
Console.WriteLine("Inside MutateWrong(): " + Value);
yield break;
}
public IEnumerable<int> MutateRight() {
Value = 7;
Console.WriteLine("Inside MutateRight(): " + Value);
return new int[0];
}
}

输出:

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

为什么在迭代器中改变结构不是编译器错误(或至少是警告)?
这种行为是一个不易理解的微妙陷阱。

匿名方法,具有相同的限制,cannot use this at all .

注意:mutable structs are evil ;这不应该在实践中出现。

最佳答案

为了证明警告的合理性,它应该出现在程序员可能会得到意想不到的结果的情况下。根据 Eric Lippert 的说法,"we try to reserve warnings for only those situations where we can say with almost certainty that the code is broken, misleading or useless."这是一个警告会产生误导的例子。

假设您有这个完全有效的——如果不是非常有用的话——对象:

struct Number
{
int value;
public Number(int value) { this.value = value; }
public int Value { get { return value; } }
// iterator that mutates "this"
public IEnumerable<int> UpTo(int max)
{
for (; value <= max; value++)
yield return value;
}
}

你有这个循环:

var num = new Number(1);
foreach (var x in num.UpTo(4))
Console.WriteLine(num.Value);

您希望此循环打印1,1,1,1,而不是1,2,3,4,对吗?所以该类(class)完全按照您的预期工作。这是一个警告不合理的例子。

既然这显然不是代码损坏、误导或无用的情况,您将如何建议编译器生成错误或警告?

关于c# - 为什么结构中的迭代器可以修改这个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4514538/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com