Skip to content

Commit eef21e2

Browse files
authored
Merge pull request #700 from CommunityToolkit/dev/2d-slice-docs
Improve XML docs for Span2D<T>.Slice(int, int, int, int)
2 parents fbaf62d + 6a0d611 commit eef21e2

File tree

4 files changed

+30
-4
lines changed

4 files changed

+30
-4
lines changed

src/CommunityToolkit.HighPerformance/Memory/Memory2D{T}.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,11 +652,12 @@ public Span2D<T> Span
652652
/// <param name="column">The target column to map within the current instance.</param>
653653
/// <param name="height">The height to map within the current instance.</param>
654654
/// <param name="width">The width to map within the current instance.</param>
655-
/// <exception cref="ArgumentException">
655+
/// <exception cref="ArgumentOutOfRangeException">
656656
/// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/>
657657
/// are negative or not within the bounds that are valid for the current instance.
658658
/// </exception>
659659
/// <returns>A new <see cref="Memory2D{T}"/> instance representing a slice of the current one.</returns>
660+
/// <remarks>See additional remarks in the <see cref="Span2D{T}.Slice(int, int, int, int)"/> docs.</remarks>
660661
public unsafe Memory2D<T> Slice(int row, int column, int height, int width)
661662
{
662663
if ((uint)row >= Height)

src/CommunityToolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,11 +665,12 @@ public ReadOnlySpan2D<T> Span
665665
/// <param name="column">The target column to map within the current instance.</param>
666666
/// <param name="height">The height to map within the current instance.</param>
667667
/// <param name="width">The width to map within the current instance.</param>
668-
/// <exception cref="ArgumentException">
668+
/// <exception cref="ArgumentOutOfRangeException">
669669
/// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/>
670670
/// are negative or not within the bounds that are valid for the current instance.
671671
/// </exception>
672672
/// <returns>A new <see cref="ReadOnlyMemory2D{T}"/> instance representing a slice of the current one.</returns>
673+
/// <remarks>See additional remarks in the <see cref="Span2D{T}.Slice(int, int, int, int)"/> docs.</remarks>
673674
public unsafe ReadOnlyMemory2D<T> Slice(int row, int column, int height, int width)
674675
{
675676
if ((uint)row >= Height)

src/CommunityToolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,11 +842,12 @@ public ref T DangerousGetReferenceAt(int i, int j)
842842
/// <param name="column">The target column to map within the current instance.</param>
843843
/// <param name="height">The height to map within the current instance.</param>
844844
/// <param name="width">The width to map within the current instance.</param>
845-
/// <exception cref="ArgumentException">
845+
/// <exception cref="ArgumentOutOfRangeException">
846846
/// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/>
847847
/// are negative or not within the bounds that are valid for the current instance.
848848
/// </exception>
849849
/// <returns>A new <see cref="ReadOnlySpan2D{T}"/> instance representing a slice of the current one.</returns>
850+
/// <remarks>See additional remarks in the <see cref="Span2D{T}.Slice(int, int, int, int)"/> docs.</remarks>
850851
public unsafe ReadOnlySpan2D<T> Slice(int row, int column, int height, int width)
851852
{
852853
if ((uint)row >= Height)

src/CommunityToolkit.HighPerformance/Memory/Span2D{T}.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,11 +999,34 @@ public ref T DangerousGetReferenceAt(int i, int j)
999999
/// <param name="column">The target column to map within the current instance.</param>
10001000
/// <param name="height">The height to map within the current instance.</param>
10011001
/// <param name="width">The width to map within the current instance.</param>
1002-
/// <exception cref="ArgumentException">
1002+
/// <exception cref="ArgumentOutOfRangeException">
10031003
/// Thrown when either <paramref name="height"/>, <paramref name="width"/> or <paramref name="height"/>
10041004
/// are negative or not within the bounds that are valid for the current instance.
10051005
/// </exception>
10061006
/// <returns>A new <see cref="Span2D{T}"/> instance representing a slice of the current one.</returns>
1007+
/// <remarks>
1008+
/// <para>
1009+
/// Contrary to <see cref="Span{T}.Slice(int, int)"/>, this method will throw an <see cref="ArgumentOutOfRangeException"/>
1010+
/// if attempting to perform a slice operation that would result in either axes being 0. That is, trying to call
1011+
/// <see cref="Slice(int, int, int, int)"/> as eg. <c>Slice(row: 1, column: 0, height: 0, width: 2)</c> on an instance
1012+
/// that has 1 row and 2 columns will throw, rather than returning a new <see cref="Span2D{T}"/> instance with 0 rows and
1013+
/// 2 columns. For contrast, trying to eg. call <c>Slice(start: 1, length: 0)</c> on a <see cref="Span{T}"/> instance of
1014+
/// length 1 would return a span of length 0, with the internal reference being set to right past the end of the memory.
1015+
/// </para>
1016+
/// <para>
1017+
/// This is by design, and it is due to the internal memory layout that <see cref="Span2D{T}"/> has. That is, in the case
1018+
/// of <see cref="Span{T}"/>, the only edge case scenario would be to obtain a new span of size 0, referencing the very end
1019+
/// of the backing object (eg. an array or a <see cref="string"/> instance). In that case, the GC can correctly track things.
1020+
/// With <see cref="Span2D{T}"/>, on the other hand, it would be possible to slice an instance with a sizeof 0 in either axis,
1021+
/// but with the computed starting reference pointing well past the end of the internal memory area. Such a behavior would not
1022+
/// be valid if the reference was pointing to a managed object, and it would cause memory corruptions (ie. "GC holes").
1023+
/// </para>
1024+
/// <para>
1025+
/// If you specifically need to be able to obtain empty values from slicing past the valid range, consider performing the range
1026+
/// validation yourself (ie. through some helper method), and then only invoking <see cref="Slice(int, int, int, int)"/> once the
1027+
/// parameters are in the accepted range. Otherwise, consider returning another return explicitly, such as <see cref="Empty"/>.
1028+
/// </para>
1029+
/// </remarks>
10071030
public unsafe Span2D<T> Slice(int row, int column, int height, int width)
10081031
{
10091032
if ((uint)row >= Height)

0 commit comments

Comments
 (0)