日期:2014-05-17  浏览次数:20979 次

IEnumerable<T>.Where(Predicate<T>)返回的集合可以看作是new出一个新的集合吗?
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里所有元素?


我不知道理解的对不对。



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

引用:
我的理解:都是指向不同的内存区域.遍历filtered的时候,和original没有关系了

我怀疑真实情况恰恰相反(ToArray()除外)。所以想确认一下。

original.ToArray();时可以认为指向不同的内存区域。

------解决方案--------------------
我觉得应该分两种情况:

对于T为值类型,则两者没关系
对于T为引用类型,不管对于Where还是ToArray,filtered集合都是New出来的,而集合的内容仍然是original内容的引用,这个可以通过筛选后修改引用类型成员变量来测试
------解决方案--------------------
IEnumerable.Where返回的是一个带predicate的迭代器。
还是建议用reflector看看源码...
------解决方案--------------------
lz可以用MSDN查下yield return
------解决方案--------------------
当然。

你修改查询的对象的状态,那么原来集合的对象也变动了。因为只是个引用而已。

如果你不想这样,就把 class Person 定义成 struct Person。
------解决方案--------------------
C# code


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);
}

------解决方案--------------------
探讨
引用:
当然。

你修改查询的对象的状态,那么原来集合的对象也变动了。

如果你不想这样,就把 class Person 定义成 struct Person。

original.Where(Predicate<T>);这里好像没有改变对象状态事儿。foreach时其实是在对original里每个元素执行Predicate,然后每次返回一个满足条件的元……

------解决方案--------------------
探讨
IEnumerable<T> original = 原始集合;
IEnumerable<T> filtered = original.Where(Predicate<T>);
我的问题是这样Where之后“新生成”的filtered是原始original的子集的同时,是在不同的内在区域?而我现在觉得不像。而且根本就没有发生“新生成”这个动作。

------解决方案--------------------
使用了IEnumerable接口的class 在对象操作时候,返回的都是对象本身. 值类型是拷贝的结果.对象类型是引用的结果.

需要谨慎操作.

楼主可以试试 修改内容,然后监视一下原来的值是否改变.

注意 修改的必须是类的属性,或者成员变量. (引用类型)