Skip to content

Commit

Permalink
Replaces the single-iteration foreach loops (#48)
Browse files Browse the repository at this point in the history
* Replaces the single-iteration foreach loops with direct calls to GetEnumerator.MoveNext().

* Adds unit tests for That and ValidState.

* Wrapping the enumerator in a try..finally to ensure it's disposed of it also implements IDisposable.

* Update Requires.cs
  • Loading branch information
scottdorman authored Sep 28, 2020
1 parent a6a5350 commit bb6a8e9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 18 deletions.
28 changes: 10 additions & 18 deletions src/Validation/Requires.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Validation
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
Expand Down Expand Up @@ -179,7 +180,7 @@ public static void NotNullOrWhiteSpace([ValidatedNotNull, NotNull] string value,
/// <param name="parameterName">The name of the parameter to include in any thrown exception.</param>
/// <exception cref="ArgumentException">Thrown if the tested condition is false.</exception>
[DebuggerStepThrough]
public static void NotNullOrEmpty([ValidatedNotNull, NotNull] System.Collections.IEnumerable values, string? parameterName)
public static void NotNullOrEmpty([ValidatedNotNull, NotNull] IEnumerable values, string? parameterName)
{
// To whoever is doing random code cleaning:
// Consider the performance when changing the code to delegate to NotNull.
Expand All @@ -189,16 +190,13 @@ public static void NotNullOrEmpty([ValidatedNotNull, NotNull] System.Collections
throw new ArgumentNullException(parameterName);
}

bool hasElements = false;
foreach (object value in values)
{
hasElements = true;
break;
}

if (!hasElements)
IEnumerator enumerator = values.GetEnumerator();
using (enumerator as IDisposable)
{
throw new ArgumentException(Format(Strings.Argument_EmptyArray, parameterName), parameterName);
if (!enumerator.MoveNext())
{
throw new ArgumentException(Format(Strings.Argument_EmptyArray, parameterName), parameterName);
}
}
}

Expand All @@ -221,14 +219,8 @@ public static void NotNullOrEmpty<T>([ValidatedNotNull, NotNull] IEnumerable<T>
throw new ArgumentNullException(parameterName);
}

bool hasElements = false;
foreach (T value in values)
{
hasElements = true;
break;
}

if (!hasElements)
using IEnumerator<T> enumerator = values.GetEnumerator();
if (!enumerator.MoveNext())
{
throw new ArgumentException(Format(Strings.Argument_EmptyArray, parameterName), parameterName);
}
Expand Down
15 changes: 15 additions & 0 deletions test/Validation.Tests/RequiresTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,19 @@ public void ValidElements()
Requires.ValidElements(new[] { "a", "b", "c", "d" }, x => !string.IsNullOrWhiteSpace(x), "param", "test message: {0}", "param");
Requires.ValidElements(new[] { 1, 2 }, v => v > 0, "param", "{0} must be greater than 0.", "param");
}

[Fact]
public void That()
{
Requires.That(true, "param", "{0} must be true.", "param");
Assert.Contains("param must be true", Assert.Throws<ArgumentException>(() => Requires.That(false, "param", "{0} must be true.", "param")).Message, StringComparison.InvariantCultureIgnoreCase);
Assert.Contains("param must be true", Assert.Throws<ArgumentException>(() => Requires.That(false, null, "{0} must be true.", "param")).Message, StringComparison.InvariantCultureIgnoreCase);
}

[Fact]
public void ValidState()
{
Requires.ValidState(true, "Condition must be true.");
Assert.Contains("Condition must be true", Assert.Throws<InvalidOperationException>(() => Requires.ValidState(false, "Condition must be true.")).Message, StringComparison.InvariantCultureIgnoreCase);
}
}

0 comments on commit bb6a8e9

Please sign in to comment.