Skip to content

Commit

Permalink
IEnumerable extension TryFirst w/ tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Kritner committed Nov 7, 2018
1 parent 3b28b79 commit 2d71368
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/Kritner.ExtensionMethods/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Kritner.ExtensionMethods
{
/// <summary>
/// <see cref="IEnumerable{T}"/> extension methods.
/// </summary>
public static class EnumerableExtensions
{
/// <summary>
/// Attempts to find the first item in <see cref="items"/>
/// meeting <see cref="Predicate{T}"/>.
///
/// Returns the <see cref="true"/> when item found,
/// <see cref="false"/> when not.
///
/// Found result is contained within out parameter <see cref="result"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="items"></param>
/// <param name="predicate"></param>
/// <param name="result"></param>
/// <returns><see cref="true"/> when item found. <see cref="false"/> otherwise.</returns>
/// <exception cref="ArgumentNullException">
/// Thrown when <see cref="items"/> or <see cref="Predicate{T}"/> is null.
/// </exception>
public static bool TryFirst<T>(
this IEnumerable<T> items,
Func<T, bool> predicate,
out T result
)
{
if (items == null)
throw new ArgumentNullException(nameof(items));
if (predicate == null)
throw new ArgumentNullException(nameof(predicate));

result = default(T);
foreach (var item in items)
{
if (predicate(item))
{
result = item;
return true;
}
}
return false;
}
}
}
16 changes: 16 additions & 0 deletions src/Kritner.ExtensionMethods/TaskExtensions.cs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Threading.Tasks;

namespace Kritner.ExtensionMethods
{
/// <summary>
/// Extension Methods for <see cref="Task"/>
/// </summary>
public static class TaskExtensions
{
/// <summary>
/// Can be used to fire off a Task and not await the reuslt.
/// </summary>
/// <param name="task"></param>
public static void FireAndForget(this Task task) { }
}
}
82 changes: 82 additions & 0 deletions test/Kritner.ExtensionMethods.Tests/EnumerableExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Kritner.ExtensionMethods.Tests
{
public class EnumerableExtensionTests
{
public class EnumerableTest
{
public int SomeInt { get; set; }
}

public static List<object[]> EnumerableTestData =>
new List<object[]>()
{
new object[]
{
new List<EnumerableTest>()
{
new EnumerableTest() { SomeInt = 1 },
new EnumerableTest() { SomeInt = 42 },
}
}
};

[Fact]
public void ShouldThrowWhenItemsNull()
{
List<EnumerableTest> items = null;

Assert.Throws<ArgumentNullException>(() =>
items.TryFirst(t => t.SomeInt == 42, out var result)
);
}

[Theory]
[MemberData(nameof(EnumerableTestData))]
public void ShouldThrowWhenPredicateNull(List<EnumerableTest> items)
{
Assert.Throws<ArgumentNullException>(() =>
items.TryFirst(null, out var result)
);
}

[Theory]
[MemberData(nameof(EnumerableTestData))]
public void ShouldReturnFalseWhenDataNotFound(List<EnumerableTest> items)
{
var found = items.TryFirst(
t => t.SomeInt == 100, out var result
);

Assert.False(found);
}

[Theory]
[MemberData(nameof(EnumerableTestData))]
public void ShouldReturnTrueWhenDataFound(List<EnumerableTest> items)
{
var found = items.TryFirst(
t => t.SomeInt == 42, out var result
);

Assert.True(found);
}

[Theory]
[MemberData(nameof(EnumerableTestData))]
public void ShouldReturnDataWhenDataFound(List<EnumerableTest> items)
{
var dataToSearch = 42;

var found = items.TryFirst(
t => t.SomeInt == dataToSearch, out var result
);

Assert.Equal(dataToSearch, result.SomeInt);
}
}
}

0 comments on commit 2d71368

Please sign in to comment.