Skip to content

Commit

Permalink
Merge pull request #1 from Kritner/master
Browse files Browse the repository at this point in the history
Initial extension methods and tests
  • Loading branch information
Kritner authored Nov 7, 2018
2 parents fb72a3b + 2d71368 commit 9892928
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 0 deletions.
39 changes: 39 additions & 0 deletions Kritner.ExtensionMethods.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2050
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{484A8DCA-7AF8-48E0-880F-4D1DB0A02FAD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AF09B244-7FC2-4077-A3D3-969DD6D68CD7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kritner.ExtensionMethods", "src\Kritner.ExtensionMethods\Kritner.ExtensionMethods.csproj", "{BDA56FBA-DD3E-489E-BA4E-175BED05D53A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kritner.ExtensionMethods.Tests", "test\Kritner.ExtensionMethods.Tests\Kritner.ExtensionMethods.Tests.csproj", "{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BDA56FBA-DD3E-489E-BA4E-175BED05D53A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BDA56FBA-DD3E-489E-BA4E-175BED05D53A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BDA56FBA-DD3E-489E-BA4E-175BED05D53A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDA56FBA-DD3E-489E-BA4E-175BED05D53A}.Release|Any CPU.Build.0 = Release|Any CPU
{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BDA56FBA-DD3E-489E-BA4E-175BED05D53A} = {484A8DCA-7AF8-48E0-880F-4D1DB0A02FAD}
{D5F701C5-FBF7-4825-BA6F-7861A4AB6F77} = {AF09B244-7FC2-4077-A3D3-969DD6D68CD7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4C63CCD4-16B5-4554-8E94-505F1390A0E9}
EndGlobalSection
EndGlobal
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;
}
}
}
7 changes: 7 additions & 0 deletions src/Kritner.ExtensionMethods/Kritner.ExtensionMethods.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

</Project>
65 changes: 65 additions & 0 deletions src/Kritner.ExtensionMethods/ListExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Kritner.ExtensionMethods
{
/// <summary>
/// <see cref="IList{T}"/> extensions.
/// </summary>
public static class ListExtensions
{
/// <summary>
/// Add object to <see cref="IList{T}"/> only when not null.
/// </summary>
/// <typeparam name="T">The type contained within the <see cref="IList{T}"/>.</typeparam>
/// <param name="obj">The <see cref="IList{T}"/>.</param>
/// <param name="item">The item to potentially add.</param>
/// <exception cref="ArgumentNullException">Thrown if <see cref="obj"/> is null</exception>
public static void AddIfNotNull<T>(this IList<T> obj, T item)
{
if (obj == null)
{
throw new ArgumentNullException($"{nameof(obj)} is null");
}

if (item == null)
{
return;
}

obj.Add(item);
}

/// <summary>
/// Adds a <see cref="IEnumerable{T}"/> to an <see cref="IList{T}"/>.
/// </summary>
/// <typeparam name="T">The type contained within the <see cref="IList{T}"/>.</typeparam>
/// <param name="obj">The <see cref="IList{T}"/>.</param>
/// <param name="item">The items to potentially add.</param>
/// <exception cref="ArgumentNullException">Thrown if <see cref="obj"/> is null</exception>
public static void AddRangeIfNotNull<T>(this IList<T> obj, IEnumerable<T> items)
{
if (obj == null)
{
throw new ArgumentNullException($"{nameof(obj)} is null");
}

if (items == null)
{
return;
}

if (obj is List<T> objList)
{
objList.AddRange(items);
return;
}

foreach (var item in items)
{
obj.Add(item);
}
}
}
}
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);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Kritner.ExtensionMethods\Kritner.ExtensionMethods.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 9892928

Please sign in to comment.