3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
10 // <OWNER>Microsoft</OWNER>
12 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
14 using System.Collections;
15 using System.Collections.Generic;
17 namespace System.Linq.Parallel
20 /// We occ----ionally need a no-op enumerator to stand-in when we don't have data left
21 /// within a partition's data stream. These are simple enumerable and enumerator
22 /// implementations that always and consistently yield no elements.
24 /// <typeparam name="T"></typeparam>
25 internal class EmptyEnumerable<T> : ParallelQuery<T>
27 private EmptyEnumerable()
28 : base(QuerySettings.Empty)
32 // A singleton cached and shared among callers.
33 private static volatile EmptyEnumerable<T> s_instance;
34 private static volatile EmptyEnumerator<T> s_enumeratorInstance;
36 internal static EmptyEnumerable<T> Instance
40 if (s_instance == null)
42 // There is no need for thread safety here.
43 s_instance = new EmptyEnumerable<T>();
50 public override IEnumerator<T> GetEnumerator()
52 if (s_enumeratorInstance == null)
54 // There is no need for thread safety here.
55 s_enumeratorInstance = new EmptyEnumerator<T>();
58 return s_enumeratorInstance;
62 internal class EmptyEnumerator<T> : QueryOperatorEnumerator<T, int>, IEnumerator<T>
64 internal override bool MoveNext(ref T currentElement, ref int currentKey)
69 // IEnumerator<T> methods.
70 public T Current { get { return default(T); } }
71 object IEnumerator.Current { get { return null; } }
72 public bool MoveNext() { return false; }
73 void Collections.IEnumerator.Reset() { }