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