我有一个从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()。
答案 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
,然后你正在改变数组的一部分(然后扔掉数组。)。这就是为什么第二个语句编译,但第一个没有编译。