为什么我的更新不会持续存在?

时间:2011-08-04 20:59:12

标签: c# linq

我有一个从linq查询填充的匿名类型(grps)。其中一个字段(DY)包含一个数组。

如果我运行此代码:

grps.ElementAt(0).Product = "kkk";

我收到编译错误。

如果我运行此代码,我没有错误,但值没有改变。

grps.ElementAt(0).DYs[0] = 19;
Console.WriteLine(grps.ElementAt(0).DYs[0]); // not 19

但是,如果我在grps上执行foreach,然后对每个数组执行嵌套步骤,我可以更改数组的值,并在嵌套循环中报告它们已更改。在嵌套循环之外,它们仍然没有改变。

我需要在匿名类型中更改数组中的值,但我无法弄清楚如何。

这让我感到恼火和困惑,因为我花了一些时间编写我认为工作正常的代码,但事实证明并没有产生任何错误。


更新

这样做的结果就是像往常一样,当我遇到问题时,因为我忘了在某事结束时坚持使用ToList()。

2 个答案:

答案 0 :(得分:7)

是的,你会得到第一个编译错误 - 你试图以匿名类型设置属性,而你不能在C#中这样做。在第二种情况下,您不是要设置属性 - 您只是在变异数组。这是一个完全不同的操作 - 就像做了类似的事情:

private readonly StringBuilder builder = new StringBuilder("hello");
...
builder.Append("Stuff");

这会更改builder引用的对象的内容;它不会更改builder变量的值。匿名类型属性在您无法更改其值的意义上是只读的 - 但如果该值是对可变对象的引用,您仍然可以改变该对象。

现在,在第二种形式中:您正在调用ElementAt两次。这意味着它将在第二次再次执行查询 - 创建一个新实例,从而创建一个新数组。您之前更改过的数组已经消失了。但是,如果你这样做:

var list = grps.ToList();
list[0].DYs[0] = 19;
Console.WriteLine(list[0].DYs[0]);

打印出19。

答案 1 :(得分:4)

为什么我的更新不会持续存在?

除非您在linq查询中使用.ToList()之类的内容,否则每次调用ElementAt(0)时都会生成不同的序列。

grps的定义在这里是关键...如果它是linq ......那就是你的问题。

为什么一个编译,但另一个不编译?

你要求一个数组.DYs,然后你正在改变数组的一部分(然后扔掉数组。)。这就是为什么第二个语句编译,但第一个没有编译。