linq-Where

        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }
 
            if (predicate == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.predicate);
            }
 
            if (source is Iterator<TSource> iterator)
            {
                return iterator.Where(predicate);
            }
 
            if (source is TSource[] array)
            {
                return array.Length == 0 ?
                    Empty<TSource>() :
                    new WhereArrayIterator<TSource>(array, predicate);
            }
 
            if (source is List<TSource> list)
            {
                return new WhereListIterator<TSource>(list, predicate);
            }
 
            return new WhereEnumerableIterator<TSource>(source, predicate);
        }
 
            public WhereEnumerableIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate)
            {
                Debug.Assert(source != null);
                Debug.Assert(predicate != null);
                _source = source;
                _predicate = predicate;
            }

原理中有一个延迟返回的方式yield,表示当实际需要数据的时候才会去执行predicate方法。返回数据。多次循环原理都是一样的,都要再去执行一下。一般都会把where到的数据存起来的。

     public static class IEnumerableExtension
    {
        public static IEnumerable<T> NewWhere<T>(this IEnumerable<T> items,Func<T,bool> predicate)
        {
            //List<T> data=new List<T>();
            foreach(var item in items)
            {
                if(predicate(item))
                {
                    //data.Add(item);
                    yield return item;
                }
            }
            //return data;
        }
    }

在自己的内部类中使用yield

     public class Iteration: IEnumerable
    {
        public List<int> lstInfo = new List<int>() { 1, 3, 5, 7, 9, 11 };
        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < lstInfo.Count; ++i)
            {
                yield return lstInfo[i];
            }
        }
    }

看一案例:

 class IteratorWorkflow
    {
        static readonly string Padding = new string(' ', 30);
 
        static IEnumerable<int> GetEnumerable()
        {
            Console.WriteLine("{0}Start of GetEnumerator()", Padding);
 
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("{0}About to yield {1}", Padding, i);
                yield return i;
                Console.WriteLine("{0}After yield", Padding);
            }
 
            Console.WriteLine("{0}Yielding final value", Padding);
            yield return -1;
 
            Console.WriteLine("{0}End of GetEnumerator()", Padding);
        }
 
        public static void Main()
        {
            IEnumerable<int> iterable = GetEnumerable();
            IEnumerator<int> iterator = iterable.GetEnumerator();
 
            Console.WriteLine("Starting to iterate");
            while (true)
            {
                Console.WriteLine("Calling MoveNext()...");
                bool result = iterator.MoveNext();
                Console.WriteLine("... MoveNext result={0}", result);
                if (!result)
                {
                    break;
                }
                Console.WriteLine("Fetching Current...");
                Console.WriteLine("... Current result={0}", iterator.Current);
            }
        }

结果是:

Starting to iterate
Calling MoveNext()...
                              Start of GetEnumerator()
                              About to yield 0
... MoveNext result=True
Fetching Current...
... Current result=0
Calling MoveNext()...
                              After yield
                              About to yield 1
... MoveNext result=True
Fetching Current...
... Current result=1
Calling MoveNext()...
                              After yield
                              About to yield 2
... MoveNext result=True
Fetching Current...
... Current result=2
Calling MoveNext()...
                              After yield
                              Yielding final value
... MoveNext result=True
Fetching Current...
... Current result=-1
Calling MoveNext()...
                              End of GetEnumerator()
... MoveNext result=False

来看下List的迭代器实现:

public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
        {
            private List<T> list;
            private int index;
            private int version;
            private T current;
 
            internal Enumerator(List<T> list) {
                this.list = list;
                index = 0;
                version = list._version;
                current = default(T);
            }
 
            public void Dispose() {
            }
 
            public bool MoveNext() {
 
                List<T> localList = list;
 
                if (version == localList._version && ((uint)index < (uint)localList._size)) 
                {                                                     
                    current = localList._items[index];                    
                    index++;
                    return true;
                }
                return MoveNextRare();
            }
 
            private bool MoveNextRare()
            {                
                if (version != list._version) {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                }
 
                index = list._size + 1;
                current = default(T);
                return false;                
            }
 
            public T Current {
                get {
                    return current;
                }
            }
 
            Object System.Collections.IEnumerator.Current {
                get {
                    if( index == 0 || index == list._size + 1) {
                         ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
                    }
                    return Current;
                }
            }
    
            void System.Collections.IEnumerator.Reset() {
                if (version != list._version) {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                }
                
                index = 0;
                current = default(T);
            }
 
        }
 

 

posted @ 2021-11-20 15:21  vba是最好的语言  阅读(42)  评论(0编辑  收藏  举报