From d8cf202fdfedef7de463a3d041e19b1941909ebf Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Wed, 2 Nov 2022 10:26:14 -0700 Subject: [PATCH 1/2] Add CollectionsMarshal.SetCount(list, count) --- .../InteropServices/CollectionsMarshal.cs | 51 +++++++++++++++++++ .../ref/System.Runtime.InteropServices.cs | 1 + .../CollectionsMarshalTests.cs | 18 +++++++ 3 files changed, 70 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs index 6a60224305a6b1..a355badc943011 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices { @@ -39,5 +40,55 @@ public static ref TValue GetValueRefOrNullRef(DictionaryItems should not be added to or removed from the while the ref is in use. public static ref TValue? GetValueRefOrAddDefault(Dictionary dictionary, TKey key, out bool exists) where TKey : notnull => ref Dictionary.CollectionsMarshalHelper.GetValueRefOrAddDefault(dictionary, key, out exists); + + /// + /// Sets the count of the to the specified value. + /// + /// + /// The list to set the count of. + /// The value to set the list's count to. + /// + /// is . + /// + /// + /// is negative/>. + /// + public static void SetCount(List list, int count) + { + if (list is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list); + } + + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException_NeedNonNegNum(nameof(count)); + } + + if (count == list._size) + { + return; + } + + list._version++; + + if (count < list._size) + { + if (RuntimeHelpers.IsReferenceOrContainsReferences()) + { + Array.Clear(list._items, count, list._size - count); + list._size = count; + } + + return; + } + + if (count > list.Capacity) + { + list.EnsureCapacity(count); + } + + list._size = count; + } } } diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index c1ace3807df844..a358941191764d 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -483,6 +483,7 @@ public static partial class CollectionsMarshal public static System.Span AsSpan(System.Collections.Generic.List? list) { throw null; } public static ref TValue GetValueRefOrNullRef(System.Collections.Generic.Dictionary dictionary, TKey key) where TKey : notnull { throw null; } public static ref TValue? GetValueRefOrAddDefault(System.Collections.Generic.Dictionary dictionary, TKey key, out bool exists) where TKey : notnull { throw null; } + public static void SetCount(System.Collections.Generic.List list, int count) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.Class, Inherited=false)] public sealed partial class ComDefaultInterfaceAttribute : System.Attribute diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs index 876c0681bc6648..bd4a55c805340e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs @@ -505,5 +505,23 @@ private class IntAsObject public int Value; public int Property { get; set; } } + + [Fact] + public void ListSetCount() + { + List list = null!; + Assert.Throws(() => CollectionsMarshal.SetCount(list, 3)); + + list = new(); + Assert.Throws(() => CollectionsMarshal.SetCount(list, -1)); + + CollectionsMarshal.SetCount(list, 5); + Assert.Equal(5, list.Count); + + list = new() { 1, 2, 3, 4, 5 }; + CollectionsMarshal.SetCount(list, 3); + Assert.Equal(3, list.Count); + Assert.Throws(() => list[3]); + } } } From b2f18d41c094b252e9b7aca607dbff1410eec39f Mon Sep 17 00:00:00 2001 From: Layomi Akinrinade Date: Thu, 17 Nov 2022 10:06:45 -0800 Subject: [PATCH 2/2] Address feedback --- .../System/Runtime/InteropServices/CollectionsMarshal.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs index a355badc943011..2df346c2d1065c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/CollectionsMarshal.cs @@ -55,11 +55,6 @@ public static ref TValue GetValueRefOrNullRef(Dictionary public static void SetCount(List list, int count) { - if (list is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list); - } - if (count < 0) { ThrowHelper.ThrowArgumentOutOfRangeException_NeedNonNegNum(nameof(count)); @@ -77,9 +72,9 @@ public static void SetCount(List list, int count) if (RuntimeHelpers.IsReferenceOrContainsReferences()) { Array.Clear(list._items, count, list._size - count); - list._size = count; } + list._size = count; return; }