使用LINQ遇到的问题,请高手解答下原理

潜意识中知道这是IEnumerable的延迟特性造成的,但是硬要条条框框地从原理上解释还真发现自己不行,所以来问问高手们了,同时我想也可以作为一个较为典型的问题,供使用着LINQ的开发者注意一下
直接看题目吧:
首先有一个MyClass类,代码如下
public   class  MyClass
{
    
private int i = 0;

    
public MyClass(int i)
    
{
        
this.i = i;
    }


    
public void MethodA()
    
{
        i
++;
    }


    
public void MethodB()
    
{
        Console.WriteLine(i);
    }

}

接着在Main函数中用两种方式返回一个MyClass的集合,分别是GetEnumerable和GetList
private   static  IEnumerable < MyClass >  GetEnumerable()
{
    
return
        intArray
        .Select(i 
=> new MyClass(i))
        .AsEnumerable();
}


private   static  IEnumerable < MyClass >  GetList()
{
    
return
        intArray
        .Select(i 
=> new MyClass(i))
        .ToList();
}
两个方法唯一的区别就在于,一个用了AsEnumerable,一个用了ToList,这里的intArray是早选定义好的private statice int[] intArray = new int[] { 1, 2, 3 };

然后调用如下
public   static   void  Main( string [] args)
{
    
//第一种情况,使用Enumerable
    IEnumerable<MyClass> ms = GetEnumerable();
    Console.WriteLine(
"第一种情况:");
    
foreach (MyClass m in ms)
    
{
        m.MethodA();
    }

    
foreach (MyClass m in ms)
    
{
        m.MethodB();
    }


    
//第二种情况,虽然ms还是IEnumberable,但事实上对象是个List
    ms = GetList();
    Console.WriteLine(
"第二种情况:");
    
foreach (MyClass m in ms)
    
{
        m.MethodA();
    }

    
foreach (MyClass m in ms)
    
{
        m.MethodB();
    }


    Console.Read();
}
对于每一种情况,都先执行MethodA使内部的i加上1,然后执行MethodB输出i
对于第二种情况,输出的是预期的2, 3, 4
而对于第一种情况,很遗憾,输出的是1, 2, 3

根据单步调试的结果, 事实上返回AsEnumerable()时,那个Select(i => new MyClass(i))每次foreach都要执行

还请高手说下原理,谢谢~

转载于:https://www.cnblogs.com/GrayZhang/archive/2008/06/12/1218631.html

猜你喜欢

转载自blog.csdn.net/weixin_34356555/article/details/93272115