diff --git a/Directory.Build.props b/Directory.Build.props index 3098049c..34a8c95f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -43,10 +43,10 @@ - + - + \ No newline at end of file diff --git a/docs/CodeDoc/Atc/Index.md b/docs/CodeDoc/Atc/Index.md index 5ca29588..880c19ac 100644 --- a/docs/CodeDoc/Atc/Index.md +++ b/docs/CodeDoc/Atc/Index.md @@ -222,6 +222,7 @@ ## [System.Collections.Generic](System.Collections.Generic.md) +- [EnumerableExtensions](System.Collections.Generic.md#enumerableextensions) - [ReadOnlyListExtensions](System.Collections.Generic.md#readonlylistextensions) ## [System.ComponentModel.DataAnnotations](System.ComponentModel.DataAnnotations.md) diff --git a/docs/CodeDoc/Atc/IndexExtended.md b/docs/CodeDoc/Atc/IndexExtended.md index 309b3299..c5e58d26 100644 --- a/docs/CodeDoc/Atc/IndexExtended.md +++ b/docs/CodeDoc/Atc/IndexExtended.md @@ -5284,6 +5284,9 @@ ## [System.Collections.Generic](System.Collections.Generic.md) +- [EnumerableExtensions](System.Collections.Generic.md#enumerableextensions) + - Static Methods + - ToAsyncEnumerable(this IEnumerable<T> source, CancellationToken cancellationToken = null) - [ReadOnlyListExtensions](System.Collections.Generic.md#readonlylistextensions) - Static Methods - GetPowerSet(this IReadOnlyList<T> list) diff --git a/docs/CodeDoc/Atc/System.Collections.Generic.md b/docs/CodeDoc/Atc/System.Collections.Generic.md index f877766c..7f822188 100644 --- a/docs/CodeDoc/Atc/System.Collections.Generic.md +++ b/docs/CodeDoc/Atc/System.Collections.Generic.md @@ -7,6 +7,29 @@
+## EnumerableExtensions +Provides extension methods for asynchronous enumeration of collections. + +>```csharp +>public static class EnumerableExtensions +>``` + +### Static Methods + +#### ToAsyncEnumerable +>```csharp +>IAsyncEnumerable ToAsyncEnumerable(this IEnumerable source, CancellationToken cancellationToken = null) +>``` +>Summary: Converts an `System.Collections.Generic.IEnumerable`1` to an `System.Collections.Generic.IAsyncEnumerable`1`. +> +>Parameters:
+>     `source`  -  The source sequence to convert.
+>     `cancellationToken`  -  A to observe while waiting for the asynchronous operation to complete.
+> +>Returns: An `System.Collections.Generic.IAsyncEnumerable`1` that contains the elements from the input sequence. + +
+ ## ReadOnlyListExtensions >```csharp diff --git a/src/Atc.XUnit/Atc.XUnit.csproj b/src/Atc.XUnit/Atc.XUnit.csproj index 92b6e23c..a4d1f3dd 100644 --- a/src/Atc.XUnit/Atc.XUnit.csproj +++ b/src/Atc.XUnit/Atc.XUnit.csproj @@ -12,7 +12,7 @@ - + NU1701 diff --git a/src/Atc/Extensions/EnumerableExtensions.cs b/src/Atc/Extensions/EnumerableExtensions.cs new file mode 100644 index 00000000..dd764ca2 --- /dev/null +++ b/src/Atc/Extensions/EnumerableExtensions.cs @@ -0,0 +1,44 @@ +// ReSharper disable once CheckNamespace +namespace System.Collections.Generic; + +/// +/// Provides extension methods for asynchronous enumeration of collections. +/// +public static class EnumerableExtensions +{ + /// + /// Converts an to an . + /// + /// The type of the elements in the source sequence. + /// The source sequence to convert. + /// A to observe while waiting for the asynchronous operation to complete. + /// An that contains the elements from the input sequence. + /// Thrown when the source sequence is null. + [SuppressMessage("Design", "MA0050:Validate arguments correctly in iterator methods", Justification = "OK - False/Positive")] + public static async IAsyncEnumerable ToAsyncEnumerable( + this IEnumerable source, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } + + await foreach (var item in IterateAsync(source, cancellationToken).ConfigureAwait(false)) + { + yield return item; + } + } + + private static async IAsyncEnumerable IterateAsync( + IEnumerable source, + [EnumeratorCancellation] CancellationToken cancellationToken) + { + foreach (var item in source) + { + cancellationToken.ThrowIfCancellationRequested(); + yield return item; + await Task.Yield(); + } + } +} \ No newline at end of file diff --git a/test/Atc.Tests/CodeComplianceTests.cs b/test/Atc.Tests/CodeComplianceTests.cs index 6bca7137..3c0351b3 100644 --- a/test/Atc.Tests/CodeComplianceTests.cs +++ b/test/Atc.Tests/CodeComplianceTests.cs @@ -40,6 +40,7 @@ public class CodeComplianceTests typeof(StackTraceHelper), // UnitTests are made, but CodeCompliance test cannot detect this + typeof(EnumerableExtensions), typeof(EnumAtcExtensions), typeof(DynamicJson), typeof(EnumHelper), diff --git a/test/Atc.Tests/Extensions/EnumerableExtensionsTests.cs b/test/Atc.Tests/Extensions/EnumerableExtensionsTests.cs new file mode 100644 index 00000000..f71fd1de --- /dev/null +++ b/test/Atc.Tests/Extensions/EnumerableExtensionsTests.cs @@ -0,0 +1,22 @@ +// ReSharper disable PossibleMultipleEnumeration +namespace Atc.Tests.Extensions; + +public class EnumerableExtensionsTests +{ + [Fact] + public async Task ToAsyncEnumerable() + { + // Arrange + var source = Enumerable.Range(1, 5); + + // Act + var result = new List(); + await foreach (var item in source.ToAsyncEnumerable()) + { + result.Add(item); + } + + // Assert + Assert.Equal(source, result); + } +} \ No newline at end of file