为什么从投影创建的整数变量不能递增?

Why can an integer variable created from projection not be incremented?

我已经 运行 进入了 C# 的一个我没想到的小众行为。幸运的是我的单元测试发现了意想不到的行为,但我很惊讶并且我不明白为什么它会这样。我用以下代码重现了这个问题。

static void Main(string[] args)
{
    var initialCollection = new bool[] { false, true };
    var projectedCollection = initialCollection.Select(o => (initialObj: o, Counter: 0)).ToArray();

    for (int i = 0; i < 10; i++)
    {
        var objectFromProjection = projectedCollection.First(o => o.initialObj == (i % 2 == 0));
        Console.WriteLine($"For initial obj {objectFromProjection.initialObj}, counter is now {++objectFromProjection.Counter}");
    }

    Console.ReadKey();
}

因为我在投影后添加了 ToArray,所以我希望计数器变量不会每次都重新初始化为零。但是,对于循环 for.

的每次迭代,它都会重新初始化为 0

这是输出:

For initial obj True, counter is now 1
For initial obj False, counter is now 1
For initial obj True, counter is now 1
For initial obj False, counter is now 1
For initial obj True, counter is now 1
For initial obj False, counter is now 1
For initial obj True, counter is now 1
For initial obj False, counter is now 1
For initial obj True, counter is now 1
For initial obj False, counter is now 1

这是我认为它会做的事情:

For initial obj True, counter is now 1
For initial obj False, counter is now 1
For initial obj True, counter is now 2
For initial obj False, counter is now 2
For initial obj True, counter is now 3
For initial obj False, counter is now 3
For initial obj True, counter is now 4
For initial obj False, counter is now 4
For initial obj True, counter is now 5
For initial obj False, counter is now 5

为什么计数器会重置为零而不是保持增量值?

因为你正在处理一个元组。观察:

for (int i = 0; i < 10; i++)
{
    var objectFromProjection = projectedCollection.First(o => o.initialObj == (i % 2 == 0));

    //Always false
    Console.WriteLine(ReferenceEquals(projectedCollection[0], objectFromProjection));
    Console.WriteLine(ReferenceEquals(projectedCollection[1], objectFromProjection));
}
 var objectFromProjection = projectedCollection.First(o => o.initialObj == (i % 2 == 0));
 Console.WriteLine($"For initial obj {objectFromProjection.initialObj}, 
                     counter is now {++objectFromProjection.Counter}");

每次循环运行都有意义 objectFromProjection ValueTuple 正在创建,它的值将始终为 1,因为 objectFromProjection 将始终具有 1 个元素,因为 .First() returns 总是一个元素..

我想这会为您澄清一些事情。

 var initialCollection = new bool[] { false, true };
  var projectedCollection = initialCollection.Select(o => (initialObj: o, Counter: 0)).ToArray();
  (bool initialObj, int Counter) d = new ValueTuple<bool,int>();
  for (int i = 0; i < 10; i++)
   {
     d = projectedCollection.First(o => o.initialObj == (i % 2 == 0));
     Console.WriteLine($"For initial obj {d.initialObj}, counter is now {++d.Counter}");
     }