none
IEnumerable接口深入研究 RRS feed

  • 问题

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

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 这是什么?

    能不能给解释一下上面的代码什么意思?

    从这里我们就可以清晰地看到M$其实是包装了一层,怎么看出来包装了一层?

    public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
        return new WhereListIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
    }这段代码又是什么?和上面的代码什么关系?

    能不能给我解释一下?


    please verify my account

    2015年1月8日 6:57

答案

  • HI  

    这是一个非常好的问题. 涉及到了 泛型,Linq,扩展方法等等.

    >>

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 这是什么?

    这是一个叫Where 的泛型扩展方法.

    返回类型是实现了 IEnumerable<T> 接口的类型. (例如 List<string> 就是这样一个类型)

    this IEnumerable<TSource> source 

    表示这个扩展方法是扩展 实现了 IEnumerable<T> 接口的类型的.

    Func<TSource, bool> predicate 这就是一个满足FUNC 委托条件的lambda表达式.

    关于FUNC 

    关于ACTION

    给楼主一个调用这个方法的例子:

     static void Main(string[] args)
            {
                List<string> list = new List<string>();
                list.Add("s1");
                list.Add("s2");
                //1.List<T> 类实现了IEnumerable<T>接口 , 可以 F12 List  查看
                //2. 这里的WHERE就是你贴出来了WHERE方法
                //3. 可以发现WHERE 方法现在System.linq.Enumerable类中,
                //但我们这里调的是List类下的方法. 这就是扩展方法的典型应用.
                var subList =list.Where(s => s == "s1");
                Console.WriteLine(subList.First());
                Console.Read();
            }

    >>

    从这里我们就可以清晰地看到M$其实是包装了一层,怎么看出来包装了一层?

    答:

    下面代码就是包装.

    因为实现IEnumerable<T>接口的类一般要么是用了yield关键字的迭代器类, 要么是数组,要么是List

    所以如果是这三种就返回这三种相对应的扩展方法.

    如果不是则返回 WhereEnumerableIterator 类的实例.

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

    >>

    public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
        return new WhereListIterator<TSource>(source, CombinePredicates(this.predicate, predicate)); 

    override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。有关继承的信息,请参见继承(C# 编程指南)

    楼主可以试着看看我写的这个例子

    namespace ConsoleApplication1
    {
        
    
        public static class ListEx
        {
            public static IList<T> Where1<T>(this IList<T> source, Func<T, bool> predicate)
            {
                List<T> list = new List<T>();
                foreach (var item in source)
                {
                    if (predicate(item))
                    {
                        list.Add(item);
                    }
                }
                return list;
            }
          
        }
        class Program
        {
           
            static void Main(string[] args)
            {
                List<string> list = new List<string>();
                list.Add("s1");
                list.Add("s2");
                Console.WriteLine(list.Where1(o=>o=="s1").First());
                Console.Read();
            }
        }
    }




    My Blog
    Please use Make as Answer if my post solved your problem and use Vote As Helpful if a post was useful.


    • 已编辑 Yuan2013 2015年1月8日 9:30
    • 已标记为答案 lctk 2015年1月9日 7:30
    2015年1月8日 9:28

全部回复

  • HI  

    这是一个非常好的问题. 涉及到了 泛型,Linq,扩展方法等等.

    >>

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 这是什么?

    这是一个叫Where 的泛型扩展方法.

    返回类型是实现了 IEnumerable<T> 接口的类型. (例如 List<string> 就是这样一个类型)

    this IEnumerable<TSource> source 

    表示这个扩展方法是扩展 实现了 IEnumerable<T> 接口的类型的.

    Func<TSource, bool> predicate 这就是一个满足FUNC 委托条件的lambda表达式.

    关于FUNC 

    关于ACTION

    给楼主一个调用这个方法的例子:

     static void Main(string[] args)
            {
                List<string> list = new List<string>();
                list.Add("s1");
                list.Add("s2");
                //1.List<T> 类实现了IEnumerable<T>接口 , 可以 F12 List  查看
                //2. 这里的WHERE就是你贴出来了WHERE方法
                //3. 可以发现WHERE 方法现在System.linq.Enumerable类中,
                //但我们这里调的是List类下的方法. 这就是扩展方法的典型应用.
                var subList =list.Where(s => s == "s1");
                Console.WriteLine(subList.First());
                Console.Read();
            }

    >>

    从这里我们就可以清晰地看到M$其实是包装了一层,怎么看出来包装了一层?

    答:

    下面代码就是包装.

    因为实现IEnumerable<T>接口的类一般要么是用了yield关键字的迭代器类, 要么是数组,要么是List

    所以如果是这三种就返回这三种相对应的扩展方法.

    如果不是则返回 WhereEnumerableIterator 类的实例.

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

    >>

    public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
        return new WhereListIterator<TSource>(source, CombinePredicates(this.predicate, predicate)); 

    override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。有关继承的信息,请参见继承(C# 编程指南)

    楼主可以试着看看我写的这个例子

    namespace ConsoleApplication1
    {
        
    
        public static class ListEx
        {
            public static IList<T> Where1<T>(this IList<T> source, Func<T, bool> predicate)
            {
                List<T> list = new List<T>();
                foreach (var item in source)
                {
                    if (predicate(item))
                    {
                        list.Add(item);
                    }
                }
                return list;
            }
          
        }
        class Program
        {
           
            static void Main(string[] args)
            {
                List<string> list = new List<string>();
                list.Add("s1");
                list.Add("s2");
                Console.WriteLine(list.Where1(o=>o=="s1").First());
                Console.Read();
            }
        }
    }




    My Blog
    Please use Make as Answer if my post solved your problem and use Vote As Helpful if a post was useful.


    • 已编辑 Yuan2013 2015年1月8日 9:30
    • 已标记为答案 lctk 2015年1月9日 7:30
    2015年1月8日 9:28
  • 写得很详细,感谢!

    please verify my account


    • 已编辑 lctk 2015年1月9日 13:13
    2015年1月9日 7:30