// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System; using System.Collections.Generic; namespace System.Linq { public static partial class EnumerableEx { /// /// Creates an enumerable sequence based on an enumerator factory function. /// /// Result sequence element type. /// Enumerator factory function. /// Sequence that will invoke the enumerator factory upon a call to GetEnumerator. public static IEnumerable Create(Func> getEnumerator) { if (getEnumerator == null) throw new ArgumentNullException("getEnumerator"); return new AnonymousEnumerable(getEnumerator); } #if HAS_AWAIT public static IEnumerable Create(Action> create) { if (create == null) throw new ArgumentNullException("create"); foreach (var x in new Yielder(create)) yield return x; } #endif class AnonymousEnumerable : IEnumerable { private readonly Func> _getEnumerator; public AnonymousEnumerable(Func> getEnumerator) { _getEnumerator = getEnumerator; } public IEnumerator GetEnumerator() { return _getEnumerator(); } Collections.IEnumerator Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } /// /// Returns a sequence with a single element. /// /// Result sequence element type. /// Single element of the resulting sequence. /// Sequence with a single element. public static IEnumerable Return(TResult value) { yield return value; } /// /// Returns a sequence that throws an exception upon enumeration. /// /// Result sequence element type. /// Exception to throw upon enumerating the resulting sequence. /// Sequence that throws the specified exception upon enumeration. public static IEnumerable Throw(Exception exception) { if (exception == null) throw new ArgumentNullException("exception"); return Throw_(exception); } private static IEnumerable Throw_(Exception exception) { throw exception; #pragma warning disable 0162 yield break; #pragma warning restore 0162 } /// /// Creates an enumerable sequence based on an enumerable factory function. /// /// Result sequence element type. /// Enumerable factory function. /// Sequence that will invoke the enumerable factory upon a call to GetEnumerator. public static IEnumerable Defer(Func> enumerableFactory) { if (enumerableFactory == null) throw new ArgumentNullException("enumerableFactory"); return Defer_(enumerableFactory); } private static IEnumerable Defer_(Func> enumerableFactory) { foreach (var item in enumerableFactory()) yield return item; } /// /// Generates a sequence by mimicking a for loop. /// /// State type. /// Result sequence element type. /// Initial state of the generator loop. /// Loop condition. /// State update function to run after every iteration of the generator loop. /// Result selector to compute resulting sequence elements. /// Sequence obtained by running the generator loop, yielding computed elements. public static IEnumerable Generate(TState initialState, Func condition, Func iterate, Func resultSelector) { if (condition == null) throw new ArgumentNullException("condition"); if (iterate == null) throw new ArgumentNullException("iterate"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return Generate_(initialState, condition, iterate, resultSelector); } private static IEnumerable Generate_(TState initialState, Func condition, Func iterate, Func resultSelector) { for (var i = initialState; condition(i); i = iterate(i)) yield return resultSelector(i); } /// /// Generates a sequence that's dependent on a resource object whose lifetime is determined by the sequence usage duration. /// /// Source element type. /// Resource type. /// Resource factory function. /// Enumerable factory function, having access to the obtained resource. /// Sequence whose use controls the lifetime of the associated obtained resource. public static IEnumerable Using(Func resourceFactory, Func> enumerableFactory) where TResource : IDisposable { if (resourceFactory == null) throw new ArgumentNullException("resourceFactory"); if (enumerableFactory == null) throw new ArgumentNullException("enumerableFactory"); return Using_(resourceFactory, enumerableFactory); } private static IEnumerable Using_(Func resourceFactory, Func> enumerableFactory) where TResource : IDisposable { using (var res = resourceFactory()) foreach (var item in enumerableFactory(res)) yield return item; } /// /// Generates a sequence by repeating the given value infinitely. /// /// Result sequence element type. /// Value to repreat in the resulting sequence. /// Sequence repeating the given value infinitely. public static IEnumerable Repeat(TResult value) { while (true) yield return value; } /// /// Generates a sequence that contains one repeated value. /// /// Result sequence element type. /// The value to be repeated. /// The number of times to repeat the value in the generated sequence. /// Sequence that contains a repeated value. public static IEnumerable Repeat(TResult element, int count) { return Enumerable.Repeat(element, count); } } }