// 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; using System.Linq; using System.Threading; namespace System.Linq { public static partial class EnumerableEx { /// /// Generates an enumerable sequence by repeating a source sequence as long as the given loop condition holds. /// /// Result sequence element type. /// Loop condition. /// Sequence to repeat while the condition evaluates true. /// Sequence generated by repeating the given sequence while the condition evaluates to true. public static IEnumerable While(Func condition, IEnumerable source) { if (condition == null) throw new ArgumentNullException("condition"); if (source == null) throw new ArgumentNullException("source"); return WhileCore(condition, source).Concat(); } static IEnumerable> WhileCore(Func condition, IEnumerable source) { while (condition()) yield return source; } /// /// Returns an enumerable sequence based on the evaluation result of the given condition. /// /// Result sequence element type. /// Condition to evaluate. /// Sequence to return in case the condition evaluates true. /// Sequence to return in case the condition evaluates false. /// Either of the two input sequences based on the result of evaluating the condition. public static IEnumerable If(Func condition, IEnumerable thenSource, IEnumerable elseSource) { if (condition == null) throw new ArgumentNullException("condition"); if (thenSource == null) throw new ArgumentNullException("thenSource"); if (elseSource == null) throw new ArgumentNullException("elseSource"); return EnumerableEx.Defer(() => condition() ? thenSource : elseSource); } /// /// Returns an enumerable sequence if the evaluation result of the given condition is true, otherwise returns an empty sequence. /// /// Result sequence element type. /// Condition to evaluate. /// Sequence to return in case the condition evaluates true. /// The given input sequence if the condition evaluates true; otherwise, an empty sequence. public static IEnumerable If(Func condition, IEnumerable thenSource) { if (condition == null) throw new ArgumentNullException("condition"); if (thenSource == null) throw new ArgumentNullException("thenSource"); return EnumerableEx.Defer(() => condition() ? thenSource : Enumerable.Empty()); } /// /// Generates an enumerable sequence by repeating a source sequence as long as the given loop postcondition holds. /// /// Result sequence element type. /// Source sequence to repeat while the condition evaluates true. /// Loop condition. /// Sequence generated by repeating the given sequence until the condition evaluates to false. public static IEnumerable DoWhile(this IEnumerable source, Func condition) { if (source == null) throw new ArgumentNullException("source"); if (condition == null) throw new ArgumentNullException("condition"); return source.Concat(While(condition, source)); } /// /// Returns a sequence from a dictionary based on the result of evaluating a selector function. /// /// Type of the selector value. /// Result sequence element type. /// Selector function used to pick a sequence from the given sources. /// Dictionary mapping selector values onto resulting sequences. /// The source sequence corresponding with the evaluated selector value; otherwise, an empty sequence. public static IEnumerable Case(Func selector, IDictionary> sources) { if (selector == null) throw new ArgumentNullException("selector"); if (sources == null) throw new ArgumentNullException("sources"); return Case(selector, sources, Enumerable.Empty()); } /// /// Returns a sequence from a dictionary based on the result of evaluating a selector function, also specifying a default sequence. /// /// Type of the selector value. /// Result sequence element type. /// Selector function used to pick a sequence from the given sources. /// Dictionary mapping selector values onto resulting sequences. /// Default sequence to return in case there's no corresponding source for the computed selector value. /// The source sequence corresponding with the evaluated selector value; otherwise, the default source. public static IEnumerable Case(Func selector, IDictionary> sources, IEnumerable defaultSource) { if (selector == null) throw new ArgumentNullException("selector"); if (sources == null) throw new ArgumentNullException("sources"); if (defaultSource == null) throw new ArgumentNullException("defaultSource"); return EnumerableEx.Defer(() => { IEnumerable result; if (!sources.TryGetValue(selector(), out result)) result = defaultSource; return result; }); } /// /// Generates a sequence by enumerating a source sequence, mapping its elements on result sequences, and concatenating those sequences. /// /// Source sequence element type. /// Result sequence element type. /// Source sequence. /// Result selector to evaluate for each iteration over the source. /// Sequence concatenating the inner sequences that result from evaluating the result selector on elements from the source. public static IEnumerable For(IEnumerable source, Func> resultSelector) { if (source == null) throw new ArgumentNullException("source"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return ForCore(source, resultSelector).Concat(); } static IEnumerable> ForCore(IEnumerable source, Func> resultSelector) { return source.Select(resultSelector); } } }