自变异只读结构域

Tak*_*est -5 c# struct readonly

我知道Eric Lippert关于情况的博客文章, 但我认为这是一个不同的情况,因为该领域自我而不是其领域.如果Enumerator只是readonly没有显示任何效果并且输出始终为0,你怎么解释调用MoveNext()?

 class SomeClass
    {
        private List<int> list;
        private [readonly] List<int>.Enumerator enumerator;

        public SomeClass()
        {
            list = new List<int>() { 1, 2, 3 };
            enumerator = list.GetEnumerator();
        }

        public int ReadValue()
        {
            if (enumerator.MoveNext())
                return enumerator.Current;
            return -1;

        }
    }
static void Main()
    {
        SomeClass c = new SomeClass();
        int value;
        while ((value = c.ReadValue()) > -1)
            MessageBox.Show(value.ToString());
    }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 11

我认为这是另一种情况

你错了.这正是我在您参考的博客文章中描述的情况.

要在此重复我的分析:对结构的每个非静态方法调用都会使用一个名为"this"的"ref"参数.我们不在参数列表中显示"ref this"参数,但它是由编译器为您生成的.ref传递的任何内容都必须是变量.由于readonly变量可能(并且在这种情况下,将会)通过调用进行变异,因此我们必须确保readonly变量永远不会被ref传递.当你在readonly结构上调用一个方法时,我们创建一个临时变量,将结构复制到临时变量,在方法调用中将ref作为"this"传递给临时变量,然后丢弃临时变量.这解释了你所看到的行为; MoveNext引起的每个突变都发生在一个副本上,然后被丢弃.

你能解释为什么这种情况 - 与我在博客中描述的情况完全相同 - 有什么不同吗?对于那些让他们与众不同的普查员,您认为哪些不同?

  • @TakeMeAsAGuest:好的,例如,对于readonly struct变量上的ToString()调用,它应该是警告,错误还是什么?这将在副本上调用ToString(); 如果ToString()改变变量,它将改变副​​本.我们是否应该告诉用户警告,或者在readonly struct变量上调用ToString()是非法的,或者是什么? (3认同)
  • @TakeMeAsAGuest:Re:动机:动机是让readonly值类型实际上是readonly; 你怎么会这样做?Re:我们复制ref-typed变量的内容吗?不,正如我曾经说过的那样,改变一个只读的ref-typed变量是*不可能*.编译器检测到这样做的尝试并在编译时禁止它,因此在运行时询问我们做什么是没有意义的.情况永远不会出现,因为这是不可能的. (2认同)
  • @TakeMeAsAGuest:你还没有说出你宁愿我们做什么,只是你不喜欢我们实际做的事情.我明白你不喜欢它.我也不是特别喜欢它.您希望看到的替代行为是什么? (2认同)