为什么在结构迭代器修改呢? [英] Why can iterators in structs modify this?

查看:229
本文介绍了为什么在结构迭代器修改呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现的价值类型的迭代方法允许修改
然而,由于在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.

推荐答案

为了证明一个警告,它应该在的情况下,程序员可能会得到意想不到的效果。据埃里克利珀,<一href="http://blogs.msdn.com/b/ericlippert/archive/2010/01/25/why-are-unused-using-directives-not-a-warning.aspx"相对=nofollow>我们设法保留警告只有那些情况下,我们几乎可以肯定地说,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?

这篇关于为什么在结构迭代器修改呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆