Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/libraries/System.Memory/ref/System.Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ public static partial class MemoryExtensions
public static int BinarySearch<T, TComparer>(this System.Span<T> span, T value, TComparer comparer) where TComparer : System.Collections.Generic.IComparer<T>, allows ref struct { throw null; }
[System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(-1)]
public static int BinarySearch<T, TComparable>(this System.Span<T> span, TComparable comparable) where TComparable : System.IComparable<T>, allows ref struct { throw null; }
public static T? Max<T>(this System.ReadOnlySpan<T> span) { throw null; }
public static T? Max<T>(this System.ReadOnlySpan<T> span, System.Collections.Generic.IComparer<T>? comparer) { throw null; }
public static T? Min<T>(this System.ReadOnlySpan<T> span) { throw null; }
public static T? Min<T>(this System.ReadOnlySpan<T> span, System.Collections.Generic.IComparer<T>? comparer) { throw null; }
[System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(-1)]
public static int CommonPrefixLength<T>(this System.Span<T> span, System.ReadOnlySpan<T> other) { throw null; }
[System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(-1)]
Expand Down
121 changes: 121 additions & 0 deletions src/libraries/System.Memory/tests/ReadOnlySpan/MinMax.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using Xunit;

namespace System.SpanTests
{
public static partial class ReadOnlySpanTests
{
[Fact]
public static void MinMax_Empty_NonNullableValueType_Throws()
{
ReadOnlySpan<int> span = ReadOnlySpan<int>.Empty;

TestHelpers.AssertThrows<InvalidOperationException, int>(span, (_span) => _span.Min());
Comment thread
manandre marked this conversation as resolved.
Outdated
TestHelpers.AssertThrows<InvalidOperationException, int>(span, (_span) => _span.Max());
Comment thread
manandre marked this conversation as resolved.
Outdated
TestHelpers.AssertThrows<InvalidOperationException, int>(span, (_span) => _span.Min(Comparer<int>.Default));
TestHelpers.AssertThrows<InvalidOperationException, int>(span, (_span) => _span.Max(Comparer<int>.Default));
}

[Fact]
public static void MinMax_Empty_ReferenceAndNullableValueType_ReturnsNull()
{
ReadOnlySpan<string?> strings = ReadOnlySpan<string?>.Empty;
ReadOnlySpan<int?> nullableInts = ReadOnlySpan<int?>.Empty;

Assert.Null(strings.Min());
Assert.Null(strings.Max());
Assert.Null(nullableInts.Min());
Assert.Null(nullableInts.Max());

Assert.Null(strings.Min(comparer: null));
Assert.Null(strings.Max(comparer: null));
Assert.Null(nullableInts.Min(comparer: null));
Assert.Null(nullableInts.Max(comparer: null));
}
Comment thread
manandre marked this conversation as resolved.
Comment thread
manandre marked this conversation as resolved.

[Fact]
public static void MinMax_AllNull_ReturnsNull()
{
ReadOnlySpan<string?> strings = new string?[] { null, null, null };
ReadOnlySpan<int?> nullableInts = new int?[] { null, null, null };

Assert.Null(strings.Min());
Assert.Null(strings.Max());
Assert.Null(nullableInts.Min());
Assert.Null(nullableInts.Max());
}

[Fact]
public static void MinMax_NullNotFirst_NullIgnoredForComparison()
{
ReadOnlySpan<string?> strings = new string?[] { "charlie", null, "bravo", null, "delta" };
ReadOnlySpan<int?> nullableInts = new int?[] { 4, null, -1, null, 7 };

Assert.Equal("bravo", strings.Min());
Assert.Equal("delta", strings.Max());
Assert.Equal(-1, nullableInts.Min());
Assert.Equal(7, nullableInts.Max());
}

[Fact]
public static void MinMax_DefaultComparer_ProducesExpectedValues()
Comment thread
manandre marked this conversation as resolved.
{
ReadOnlySpan<int> ints = new int[] { 4, -1, 7, 2 };
ReadOnlySpan<string?> strings = new string?[] { null, "charlie", "bravo", null, "delta" };

Assert.Equal(-1, ints.Min());
Assert.Equal(7, ints.Max());

Assert.Equal("bravo", strings.Min());
Assert.Equal("delta", strings.Max());
}

[Fact]
public static void MinMax_CustomComparer_IsUsed()
{
ReadOnlySpan<int> ints = new int[] { 4, -1, 7, 2 };
IComparer<int> reverse = Comparer<int>.Create((left, right) => right.CompareTo(left));
Comment thread
manandre marked this conversation as resolved.

Assert.Equal(7, ints.Min(reverse));
Assert.Equal(-1, ints.Max(reverse));
}

[Fact]
public static void MinMax_IntegerTypes_DefaultAndNullComparer_ProduceExpectedValues()
{
AssertMinMaxValues(new byte[] { 12, 3, 255, 7 }, (byte)3, (byte)255);
AssertMinMaxValues(new sbyte[] { 12, -9, 100, 7 }, (sbyte)-9, (sbyte)100);
AssertMinMaxValues(new ushort[] { 12, 3, 65535, 7 }, (ushort)3, ushort.MaxValue);
AssertMinMaxValues(new short[] { 12, -9, 100, 7 }, (short)-9, (short)100);
AssertMinMaxValues(new char[] { 'x', 'b', 'm', 'z' }, 'b', 'z');
AssertMinMaxValues(new uint[] { 12u, 3u, 400u, 7u }, 3u, 400u);
AssertMinMaxValues(new int[] { 12, -9, 400, 7 }, -9, 400);
AssertMinMaxValues(new ulong[] { 12ul, 3ul, 400ul, 7ul }, 3ul, 400ul);
AssertMinMaxValues(new long[] { 12L, -9L, 400L, 7L }, -9L, 400L);
AssertMinMaxValues(new nuint[] { (nuint)12, (nuint)3, (nuint)400, (nuint)7 }, (nuint)3, (nuint)400);
AssertMinMaxValues(new nint[] { (nint)12, (nint)(-9), (nint)400, (nint)7 }, (nint)(-9), (nint)400);
AssertMinMaxValues(new Int128[] { (Int128)12, (Int128)(-9), (Int128)400, (Int128)7 }, (Int128)(-9), (Int128)400);
AssertMinMaxValues(new UInt128[] { (UInt128)12, (UInt128)3, (UInt128)400, (UInt128)7 }, (UInt128)3, (UInt128)400);
}

private static void AssertMinMaxValues<T>(T[] values, T expectedMin, T expectedMax)
where T : IComparable<T>
{
ReadOnlySpan<T> span = values;
IComparer<T> comparer = Comparer<T>.Create(static (left, right) => left.CompareTo(right));
IComparer<T> reverseComparer = Comparer<T>.Create(static (left, right) => right.CompareTo(left));

Assert.Equal(expectedMin, span.Min());
Assert.Equal(expectedMax, span.Max());
Assert.Equal(expectedMin, span.Min(comparer: null));
Assert.Equal(expectedMax, span.Max(comparer: null));
Assert.Equal(expectedMin, span.Min(comparer));
Assert.Equal(expectedMax, span.Max(comparer));
Assert.Equal(expectedMax, span.Min(reverseComparer));
Assert.Equal(expectedMin, span.Max(reverseComparer));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<Compile Include="ParsersAndFormatters\Formatter\RealFormatterTests.cs" />
<Compile Include="$(CommonPath)..\tests\System\RealParserTestsBase.cs" Link="ParsersAndFormatters\Parser\RealParserTestsBase.cs" />
<Compile Include="ParsersAndFormatters\Parser\RealParserTests.cs" />
<Compile Include="ReadOnlySpan\MinMax.cs" />
<Compile Include="ReadOnlySpan\Comparers.cs" />
<Compile Include="ReadOnlySpan\Contains.byte.cs" />
<Compile Include="ReadOnlySpan\Contains.T.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4486,4 +4486,7 @@
<data name="Arg_HexBinaryStylesNotSupported" xml:space="preserve">
<value>The number styles AllowHexSpecifier and AllowBinarySpecifier are not supported on the decimal type.</value>
</data>
<data name="InvalidOperation_NoElements" xml:space="preserve">
<value>Sequence contains no elements.</value>
</data>
</root>
Loading
Loading