为什么在结构迭代器修改呢?结构、迭代

2023-09-02 02:10:30 作者:曾经年少爱追梦

我发现的价值类型的迭代方法允许修改 。 然而,由于在CLR局限性,修改的不见通过调用方法。 (是按值传递)

I discovered that iterator methods in value types are allowed to modify this. However, due to limitations in the CLR, the modifications are not seen by the calling method. (this is passed by value)

因此​​,相同的code在一个迭代和非迭代器产生不同的结果:

Therefore, identical code in an iterator and a non-iterator produce different results:

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(): 7
After MutateWrong(): 0

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

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

Why isn't it a compiler error (or at least warning) to mutate a struct in an iterator? This behavior is a subtle trap which is not easily understood.

匿名方法,它们共享相同的限制,不能使用在所有。

Anonymous methods, which share the same limitation, cannot use this at all.

注:可变的结构是邪恶的;这不应该拿出实际。的

Note: mutable structs are evil; this should never come up in practice.

推荐答案

为了证明一个警告,它应该在的情况下,程序员可能会得到意想不到的效果。据埃里克利珀,我们设法保留警告只有那些情况下,我们几乎可以肯定地说,code是坏了,误导或无用的话。这里有一个实例,其中警告会产生误导

In order to justify a warning, it should be in a situation where the programmer is likely to get unexpected results. According to 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." Here is an instance where the warning would be misleading.

让我们说你有这个完全有效的 - 如果不是非常有用 - 对象:

Let's say you have this perfectly valid -- if not terribly useful -- object:

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 ,对不对?所以类的工作完全按照你期望的那样。这是一个实例,其中警告是没有道理的。

You'd expect this loop to print 1,1,1,1, not 1,2,3,4, right? So the class works exactly as you expect. This is an instance where the warning would be unjustified.

由于这显然不是一种情况:code被打破,误导,还是没用,你会如何建议,编译器生成错误或警告?

Since this is clearly not a situation where the code is broken, misleading, or useless, how would you propose that the compiler generate an error or warning?

 
精彩推荐
图片推荐