繁体   English   中英

延迟执行时linq c#中的奇怪行为

[英]Strange behaviour in linq c# under delayed execution

嗨,我有以下代码,产生一种奇怪的行为。 由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); 
  }

 }

输出:在列表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 } ;

实际上并不创建对象。 它只是创建一个对象,迭代时实际创建对象。 也就是说,您可以将query1视为知道如何在请求时吐出对象的规则。 所以当你这样做时:

foreach (MyClassExtrax fj in query1)
{
    fj.v1.val = 40;
    fj.prop1 = 40;   //property does not get updated..
}

然后这个:

foreach (MyClassExtrax obj in query1)
{
   Console.WriteLine("in MyClassExtra list v1.val is {0}, prop1 is {1}  ", obj.v1.val, obj.prop1); 
}

您正在执行两次生成对象的规则。 也就是说,产生两个不同的对象序列,并且它们不在序列之间共享。 这就是为什么你没有看到更新的值; 序列的两次迭代中的引用不相同。

但是,当您调用ToList ,然后遍历结果列表时,现在您只生成了一个对象序列,并且在两次迭代中,该对象序列显然是相同的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM