嗨,我有以下代码,产生一种奇怪的行为.由linq到Objects生成的IEnumerable中包含的对象实例的属性不会在后续的foreach语句中更新.foreach语句应该枚举IEnumerable.相反,解决方案是先将其枚举.
虽然我找到了解决方案,但我没有在书籍或文章中的任何地方看到这些,并处理类似的例子.也许对linq有错综复杂知识的人可以解释它.
我花了一天的时间来确定错误的确切原因,并且在大型应用程序中调试并不容易.然后我在一个更简单的环境中复制它,如下所示.
public class MyClass
{
public int val ;
}
public class MyClassExtrax
{
public MyClass v1 { get; set; }
public int prop1 { get; set; }
}
void Main()
{
List <MyClass> list1 = new List<MyClass>();
MyClass obj1 = new MyClass(); obj1.val = 10;
list1.Add(obj1);
MyClass obj2 = new MyClass();
obj2.val = 10;
list1.Add(obj2);
IEnumerable<MyClassExtrax> query1 =
from v in list1
where v.val >= 0
select new MyClassExtrax{ v1=v , prop1=0 } ;
//query1=query1.ToList(); solves the problem..but why is this needed..?
foreach (MyClassExtrax fj in query1)
{
fj.v1.val = 40;
fj.prop1 = 40; //property does not get updated..
}
foreach (MyClass obj in list1)
{
Console.WriteLine("in list 1 value is {0} : ", obj.val);
}
foreach (MyClassExtrax obj in query1)
{
Console.WriteLine("in MyClassExtra list v1.val is {0}, prop1 is {1} ", obj.v1.val, obj.prop1);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:在列表1中的值为40:
在列表1中的值是40:
在MyClassExtra列表中,v1.val为40,prop1为0
在MyClassExtra列表中,v1.val为40,prop1为0
如你所见,prop1没有更新到40.!!
这很简单,有很好的记录.这是因为LINQ 的延迟执行功能.这段代码
IEnumerable<MyClassExtrax> query1 =
from v in list1
where v.val >= 0
select new MyClassExtrax{ v1=v , prop1=0 } ;
Run Code Online (Sandbox Code Playgroud)
实际上并不创建对象.它只是创建一个对象,迭代时实际创建对象.也就是说,您可以将其query1视为知道如何在请求时吐出对象的规则.所以当你这样做时:
foreach (MyClassExtrax fj in query1)
{
fj.v1.val = 40;
fj.prop1 = 40; //property does not get updated..
}
Run Code Online (Sandbox Code Playgroud)
然后这个:
foreach (MyClassExtrax obj in query1)
{
Console.WriteLine("in MyClassExtra list v1.val is {0}, prop1 is {1} ", obj.v1.val, obj.prop1);
}
Run Code Online (Sandbox Code Playgroud)
您正在执行两次生成对象的规则.也就是说,产生两个不同的对象序列,并且它们不在序列之间共享.这就是为什么你没有看到更新的值; 序列的两次迭代中的引用不相同.
但是,当您调用ToList,然后遍历结果列表时,现在您只生成了一个对象序列,并且在两次迭代中,该对象序列显然是相同的.
| 归档时间: |
|
| 查看次数: |
189 次 |
| 最近记录: |