Add IReadOnlyList<T>.Slice

This commit is contained in:
Oliver Booth 2022-12-01 13:51:30 +00:00
parent e02fd3b1b4
commit b60fdc495b
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
3 changed files with 127 additions and 1 deletions

View File

@ -21,6 +21,7 @@
- X10D: Added `IList<T>.RemoveRange(Range)`
- X10D: Added `IList<T>.Swap(IList<T>)` (#62)
- X10D: Added `IReadOnlyList<T>.IndexOf(T[, int[, int]])`
- X10D: Added `IReadOnlyList<T>.Slice(int[, int]])`
- X10D: Added `Point.IsOnLine(LineF)`, `Point.IsOnLine(PointF, PointF)`, and `Point.IsOnLine(Vector2, Vector2)`
- X10D: Added `PointF.IsOnLine(LineF)`, `PointF.IsOnLine(PointF, PointF)`, and `PointF.IsOnLine(Vector2, Vector2)`
- X10D: Added `Point.ToSize()`

View File

@ -216,6 +216,58 @@ public class ListTests
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.Shuffle());
}
[TestMethod]
public void Slice_ShouldReturnCorrectValue_GivenStartIndex()
{
int[] array = {0, 1, 2, 3, 4, 5};
CollectionAssert.AreEqual(new[] {2, 3, 4, 5}, array.Slice(2).ToArray());
}
[TestMethod]
public void Slice_ShouldReturnCorrectValue_GivenStartIndexAndLength()
{
int[] array = {0, 1, 2, 3, 4, 5};
CollectionAssert.AreEqual(new[] {2, 3, 4}, array.Slice(2, 3).ToArray());
}
[TestMethod]
public void Slice_ShouldReturnEmptyList_ForEmptyList()
{
int[] array = Array.Empty<int>();
CollectionAssert.AreEqual(Array.Empty<int>(), array.Slice(0).ToArray());
CollectionAssert.AreEqual(Array.Empty<int>(), array.Slice(0, 0).ToArray());
}
[TestMethod]
public void Slice_ShouldThrowArgumentNullException_GivenNullList()
{
int[]? array = null;
Assert.ThrowsException<ArgumentNullException>(() => array!.Slice(0));
Assert.ThrowsException<ArgumentNullException>(() => array!.Slice(0, 0));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenNegativeCount()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(0, -1));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenNegativeStartIndex()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(-1));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(-1, 0));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenInvalidStartIndexCountPair()
{
int[] array = {0, 1, 2};
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(2, 4));
}
[TestMethod]
public void Swap_ShouldThrowArgumentNullException_GivenNullSource()
{

View File

@ -1,4 +1,3 @@
using System.Diagnostics;
using System.Diagnostics.Contracts;
using X10D.Core;
@ -320,6 +319,80 @@ public static class ListExtensions
}
}
/// <summary>
/// Forms a slice out of the current list that begins at a specified index.
/// </summary>
/// <param name="source">The list to slice.</param>
/// <param name="start">The index at which to begin the slice.</param>
/// <typeparam name="T">The type of elements in <paramref name="source" />.</typeparam>
/// <returns>
/// A list that consists of all elements of the current list from <paramref name="start" /> to the end of the list.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="start" /> is less than zero or greater than <see cref="IReadOnlyList{T}.Count" />.
/// </exception>
public static IReadOnlyList<T> Slice<T>(this IReadOnlyList<T> source, int start)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(source);
#else
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
#endif
return source.Slice(start, source.Count - start);
}
/// <summary>
/// Forms a slice out of the current list that begins at a specified index for a specified length.
/// </summary>
/// <param name="source">The list to slice.</param>
/// <param name="start">The index at which to begin the slice.</param>
/// <param name="length">The desired length for the slice.</param>
/// <typeparam name="T">The type of elements in <paramref name="source" />.</typeparam>
/// <returns>
/// A list that consists of all elements of the current list from <paramref name="start" /> to the end of the list.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="start" /> or <paramref name="start" /> + <paramref name="length" /> is less than zero or greater than
/// <see cref="IReadOnlyList{T}.Count" />.
/// </exception>
public static IReadOnlyList<T> Slice<T>(this IReadOnlyList<T> source, int start, int length)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(source);
#else
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
#endif
if (start < 0 || start > source.Count)
{
throw new ArgumentOutOfRangeException(nameof(start), ExceptionMessages.IndexOutOfRange);
}
if (length < 0 || length > source.Count - start)
{
throw new ArgumentOutOfRangeException(nameof(length), ExceptionMessages.CountMustBeInRange);
}
var sliced = new List<T>();
int endIndex = start + length;
for (int index = start; index < endIndex; index++)
{
sliced.Add(source[index]);
}
return sliced.AsReadOnly();
}
/// <summary>
/// Swaps all elements in a list with the elements in another list.
/// </summary>