IEnumerable<T> original = 原始集合;
IEnumerable<T> filtered = original.Where(Predicate<T>);假如这样,original与filtered是指向内存中独立的区域吗?如果不是,那么每次foreach(var t in filtered)时,等于都会遍历一遍original里所有元素?假如:
IEnumerable<T> original = 原始集合;
IEnumerable<T> filtered = original.ToArray();
这时再foreach(var t in filtered),这时就不是遍历original里所有元素?
我不知道理解的对不对。

解决方案 »

  1.   

    IEnumerable<T> original = 原始集合;
    IEnumerable<T> filtered = original.Where(Predicate<T>);
    或者
    IEnumerable<T> original = 原始集合;
    IEnumerable<T> filtered = original.ToArray();
    我的理解:都是指向不同的内存区域.遍历filtered的时候,和original没有关系了
      

  2.   

    我怀疑真实情况恰恰相反(ToArray()除外)。所以想确认一下。original.ToArray();时可以认为指向不同的内存区域。
      

  3.   


    class Program
    {
        static readonly Person[] peopel = 
        {
            new Person { Name="xhtmldivcss00", Age= 300 },
            new Person { Name="xhtmldivcss01", Age= 301 },
            new Person { Name="xhtmldivcss02", Age= 302 },
            new Person { Name="xhtmldivcss03", Age= 303 },
            new Person { Name="xhtmldivcss04", Age= 304 },
            new Person { Name="xhtmldivcss05", Age= 305 },
            new Person { Name="xhtmldivcss06", Age= 306 },
            new Person { Name="xhtmldivcss07", Age= 307 },
            new Person { Name="xhtmldivcss08", Age= 308 },
            new Person { Name="xhtmldivcss09", Age= 309 },
            new Person { Name="xhtmldivcss10", Age= 310 },
             
        };
        static void Main(string[] args)
        {
            IEnumerable<Person> group = peopel;
            IEnumerable<Person> filtered1 = group.Where(p => p.Age > 308);
            foreach (var p in filtered1)
                Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);        IEnumerable<Person> filtered2 = group.Where(p => p.Name.Contains("7"));        Console.WriteLine("----------- filtered 2 ");
            foreach( var p in filtered2)
                Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);        Console.WriteLine("----------- filtered 3 ");
            IEnumerable<Person> filtered3 = group.Where(p => p.Age < 303).ToArray();
            foreach(var p in filtered3)
                Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);        Console.WriteLine("----------- Array");
            foreach(var p in filtered3)
                Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);
            Console.Read();    }
    }
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    也就是说遍历filtered1, filtered2, filtered3时都等于遍历group(原始集合)里的每个元素,也包括.ToArray()时。直到最后一次遍历(已经转换成Array)时,才是在遍历内存中与group另外的内存区域,之前三个foreach都是在遍历group的内存区域。不知道我理解的对不对。
      

  4.   

    我觉得应该分两种情况:对于T为值类型,则两者没关系
    对于T为引用类型,不管对于Where还是ToArray,filtered集合都是New出来的,而集合的内容仍然是original内容的引用,这个可以通过筛选后修改引用类型成员变量来测试
      

  5.   

    IEnumerable.Where返回的是一个带predicate的迭代器。
    还是建议用reflector看看源码...
      

  6.   

    lz可以用MSDN查下yield return
      

  7.   

    Enumerator的一种简易实现方法而已。我现在问的关键不在这个。IEnumerable<T> original = 原始集合;
    IEnumerable<T> filtered = original.Where(Predicate<T>);
    我的问题是这样Where之后“新生成”的filtered是原始original的子集的同时,是在不同的内在区域?而我现在觉得不像。而且根本就没有发生“新生成”这个动作。
      

  8.   

    本帖最后由 caozhy 于 2011-06-07 10:26:28 编辑
      

  9.   

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        if (predicate == null)
        {
            throw Error.ArgumentNull("predicate");
        }
        if (source is Iterator<TSource>)
        {
            return ((Iterator<TSource>) source).Where(predicate);
        }
        if (source is TSource[])
        {
            return new WhereArrayIterator<TSource>((TSource[]) source, predicate);
        }
        if (source is List<TSource>)
        {
            return new WhereListIterator<TSource>((List<TSource>) source, predicate);
        }
        return new WhereEnumerableIterator<TSource>(source, predicate);
    }
      

  10.   

    original.Where(Predicate<T>);这里好像没有改变对象状态事儿。foreach时其实是在对original里每个元素执行Predicate,然后每次返回一个满足条件的元素供foreach块内的语句处理,而不是返回一个满足条件的子集(且在独立内存区域)。<-------这就是我的猜测,我只是想确认一下这个猜测。
      

  11.   

    没有什么新生成一说,IEnumerable<T> filtered = original.Where(Predicate<T>);此时filtered结果集中还没有元素,只有在你foreach遍历的时候才会生成结果集,而结果集是从原集合中遍历筛选符合条件的元素,但并不是生成一个新的集合对象,对结果集中元素的操作的仍是对原集合元素的操作
      

  12.   

    使用了IEnumerable接口的class 在对象操作时候,返回的都是对象本身. 值类型是拷贝的结果.对象类型是引用的结果.需要谨慎操作.楼主可以试试 修改内容,然后监视一下原来的值是否改变.注意 修改的必须是类的属性,或者成员变量. (引用类型)
      

  13.   


    ok! that's it! 这就是我想确认的东西!
      

  14.   

    而且Where不是一次性整个地返回某个满足条件的子集,而是每次只返回一个,right?