Skip to content

Commit

Permalink
FallbackIfEmpty: add overloads taking Func<T> parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
fsateler committed May 12, 2017
1 parent d47537b commit e39fc66
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 1 deletion.
22 changes: 21 additions & 1 deletion MoreLinq.Test/FallbackIfEmptyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void FallbackIfEmptyWithNullSequence()
[Test]
public void FallbackIfEmptyWithNullFallbackParams()
{
Assert.ThrowsArgumentNullException("fallback", () => new[] { 1 }.FallbackIfEmpty(null));
Assert.ThrowsArgumentNullException("fallback", () => new[] { 1 }.FallbackIfEmpty((int[])null));
}

[Test]
Expand All @@ -51,9 +51,29 @@ public void FallbackIfEmptyWithEmptySequence()
source.FallbackIfEmpty(12, 23, 34, 45).AssertSequenceEqual(12, 23, 34, 45);
source.FallbackIfEmpty(12, 23, 34, 45, 56).AssertSequenceEqual(12, 23, 34, 45, 56);
source.FallbackIfEmpty(12, 23, 34, 45, 56, 67).AssertSequenceEqual(12, 23, 34, 45, 56, 67);
source.FallbackIfEmpty(() => 12).AssertSequenceEqual(12);
source.FallbackIfEmpty(() => 12, () => 23).AssertSequenceEqual(12, 23);
source.FallbackIfEmpty(() => 12, () => 23, () => 34).AssertSequenceEqual(12, 23, 34);
source.FallbackIfEmpty(() => 12, () => 23, () => 34, () => 45).AssertSequenceEqual(12, 23, 34, 45);
source.FallbackIfEmpty(() => 12, () => 23, () => 34, () => 45, () => 56).AssertSequenceEqual(12, 23, 34, 45, 56);
source.FallbackIfEmpty(() => 12, () => 23, () => 34, () => 45, () => 56, () => 67).AssertSequenceEqual(12, 23, 34, 45, 56, 67);
// ReSharper restore PossibleMultipleEnumeration
}

[Test]
public void FallbackIfEmptyDoesNotInvokeFunctionsIfCollectionIsNonEmpty()
{
var func = BreakingFunc.Of<int>();
var source = new[] { 1 };

source.FallbackIfEmpty(func).AssertSequenceEqual(source);
source.FallbackIfEmpty(func, func).AssertSequenceEqual(source);
source.FallbackIfEmpty(func, func, func).AssertSequenceEqual(source);
source.FallbackIfEmpty(func, func, func, func).AssertSequenceEqual(source);
source.FallbackIfEmpty(func, func, func, func, func).AssertSequenceEqual(source);
source.FallbackIfEmpty(func, func, func, func, func, func).AssertSequenceEqual(source);
}

[Test]
public void FallbackIfEmptyWithEmptySequenceCollectionOptimized()
{
Expand Down
156 changes: 156 additions & 0 deletions MoreLinq/FallbackIfEmpty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,162 @@ public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, IEnu
return FallbackIfEmptyImpl(source, 0, default(T), default(T), default(T), default(T), fallback);
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactory">A function that generates the first value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, Func<T> fallbackFactory)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactory == null) throw new ArgumentNullException(nameof(fallbackFactory));
return FallbackIfEmpty(source, 1, fallbackFactory, null, null, null);
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactory1">A function that generates the first value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory2">A function that generates the second value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, Func<T> fallbackFactory1, Func<T> fallbackFactory2)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactory1 == null) throw new ArgumentNullException(nameof(fallbackFactory1));
if (fallbackFactory2 == null) throw new ArgumentNullException(nameof(fallbackFactory2));
return FallbackIfEmpty(source, 2, fallbackFactory1, fallbackFactory2, null, null);
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactory1">A function that generates the first value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory2">A function that generates the second value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory3">A function that generates the third value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, Func<T> fallbackFactory1, Func<T> fallbackFactory2, Func<T> fallbackFactory3)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactory1 == null) throw new ArgumentNullException(nameof(fallbackFactory1));
if (fallbackFactory2 == null) throw new ArgumentNullException(nameof(fallbackFactory2));
if (fallbackFactory3 == null) throw new ArgumentNullException(nameof(fallbackFactory3));
return FallbackIfEmpty(source, 3, fallbackFactory1, fallbackFactory2, fallbackFactory3, null);
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactory1">A function that generates the first value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory2">A function that generates the second value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory3">A function that generates the third value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <param name="fallbackFactory4">A function that generates the fourth value of the alternate sequence that
/// is returned if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, Func<T> fallbackFactory1, Func<T> fallbackFactory2, Func<T> fallbackFactory3, Func<T> fallbackFactory4)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactory1 == null) throw new ArgumentNullException(nameof(fallbackFactory1));
if (fallbackFactory2 == null) throw new ArgumentNullException(nameof(fallbackFactory2));
if (fallbackFactory3 == null) throw new ArgumentNullException(nameof(fallbackFactory3));
if (fallbackFactory4 == null) throw new ArgumentNullException(nameof(fallbackFactory4));
return FallbackIfEmpty(source, 4, fallbackFactory1, fallbackFactory2, fallbackFactory3, fallbackFactory4);
}

private static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, int count, Func<T> fallbackFactory1, Func<T> fallbackFactory2, Func<T> fallbackFactory3, Func<T> fallbackFactory4)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (count < 0 || count > 4) {
throw new ArgumentException(nameof(count));
}
return FallbackIfEmptyImpl(source, null, default(T), default(T), default(T), default(T), fallback());
IEnumerable<T> fallback()
{
yield return fallbackFactory1();
if (count > 1) yield return fallbackFactory2();
if (count > 2) yield return fallbackFactory3();
if (count > 3) yield return fallbackFactory4();
}
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence from an array of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactories">The array of functions that generate the values of the alternate
/// sequence if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, params Func<T>[] fallbackFactories)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactories == null) throw new ArgumentNullException(nameof(fallbackFactories));

return FallbackIfEmpty(source, (IEnumerable<Func<T>>)fallbackFactories);
}

/// <summary>
/// Returns the elements of a sequence, but if it is empty then
/// returns an altenate sequence from an array of values.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequences.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="fallbackFactories">The sequence of functions that generate the values of the alternate
/// sequence if <paramref name="source"/> is empty.</param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> that containing fallback values
/// if <paramref name="source"/> is empty; otherwise, <paramref name="source"/>.
/// </returns>

public static IEnumerable<T> FallbackIfEmpty<T>(this IEnumerable<T> source, IEnumerable<Func<T>> fallbackFactories)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (fallbackFactories == null) throw new ArgumentNullException(nameof(fallbackFactories));

return FallbackIfEmptyImpl(source, null, default(T), default(T), default(T), default(T), fallbackFactories.Select(f => f()));
}

static IEnumerable<T> FallbackIfEmptyImpl<T>(IEnumerable<T> source,
int? count, T fallback1, T fallback2, T fallback3, T fallback4,
IEnumerable<T> fallback)
Expand Down

0 comments on commit e39fc66

Please sign in to comment.