Skip to content

Commit 032569f

Browse files
committed
CollectionsExtensions.{AddRange,InsertRange,CopyTo,AsReadOnly}
1 parent fbb7902 commit 032569f

8 files changed

Lines changed: 527 additions & 2 deletions

File tree

src/MonoMod.Backports.Shims/MonoMod.Backports.Shims.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.Build.NoTargets">
1+
<Project Sdk="Microsoft.Build.NoTargets">
22

33
<PropertyGroup>
44
<IsPackable>true</IsPackable>
@@ -18,6 +18,10 @@
1818
<PackInference Remove="@(PackInference)" />
1919
</ItemGroup>
2020

21+
<ItemDefinitionGroup>
22+
<ExtraShimPackageVersion Visible="false" />
23+
</ItemDefinitionGroup>
24+
2125
<!-- Packages we're going to shim -->
2226
<ItemGroup>
2327
<PackageReference Include="Microsoft.Bcl.HashCode" Version="6.0.0" Shim="true" />

src/MonoMod.Backports/MonoMod.Backports.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<!-- target frameworks are defined in Common.props -->
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#if NET8_0_OR_GREATER
2+
#define HAS_LISTSPANMETHODS
3+
#endif
4+
#if NET7_0_OR_GREATER
5+
#define HAS_ASREADONLY
6+
#endif
7+
8+
using System.Collections.ObjectModel;
9+
using System.Diagnostics.CodeAnalysis;
10+
#if !HAS_LISTSPANMETHODS
11+
using System.Runtime.InteropServices;
12+
#endif
13+
14+
namespace System.Collections.Generic
15+
{
16+
[SuppressMessage("Design", "CA1002:Do not expose generic lists",
17+
Justification = "Replicating existing APIs")]
18+
public static class CollectionExtensionsEx
19+
{
20+
public static void AddRange<T>(
21+
#if !HAS_LISTSPANMETHODS
22+
this
23+
#endif
24+
List<T> list, params ReadOnlySpan<T> source
25+
)
26+
{
27+
#if HAS_LISTSPANMETHODS
28+
list.AddRange(source);
29+
#else
30+
ThrowHelper.ThrowIfArgumentNull(list, ExceptionArgument.list);
31+
if (source.IsEmpty)
32+
{
33+
return;
34+
}
35+
var currentCount = list.Count;
36+
CollectionsMarshal.SetCount(list, currentCount + source.Length);
37+
source.CopyTo(CollectionsMarshal.AsSpan(list).Slice(currentCount + 1));
38+
#endif
39+
}
40+
41+
public static void InsertRange<T>(
42+
#if !HAS_LISTSPANMETHODS
43+
this
44+
#endif
45+
List<T> list, int index, params ReadOnlySpan<T> source
46+
)
47+
{
48+
#if HAS_LISTSPANMETHODS
49+
list.InsertRange(index, source);
50+
#else
51+
ThrowHelper.ThrowIfArgumentNull(list, ExceptionArgument.list);
52+
if ((uint)index > (uint)list.Count)
53+
{
54+
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
55+
}
56+
if (source.IsEmpty)
57+
{
58+
return;
59+
}
60+
var currentCount = list.Count;
61+
CollectionsMarshal.SetCount(list, currentCount + source.Length);
62+
var items = CollectionsMarshal.AsSpan(list);
63+
if (index < currentCount)
64+
{
65+
items.Slice(index, currentCount - index).CopyTo(items.Slice(index + source.Length));
66+
}
67+
source.CopyTo(items.Slice(index));
68+
#endif
69+
}
70+
71+
public static void CopyTo<T>(
72+
#if !HAS_LISTSPANMETHODS
73+
this
74+
#endif
75+
List<T> list, Span<T> destination
76+
)
77+
{
78+
#if HAS_LISTSPANMETHODS
79+
list.CopyTo(destination);
80+
#else
81+
ThrowHelper.ThrowIfArgumentNull(list, ExceptionArgument.list);
82+
CollectionsMarshal.AsSpan(list).CopyTo(destination);
83+
#endif
84+
}
85+
86+
public static ReadOnlyCollection<T> AsReadOnly<T>(
87+
#if !HAS_ASREADONLY
88+
this
89+
#endif
90+
IList<T> list
91+
) => new(list);
92+
93+
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(
94+
#if !HAS_ASREADONLY
95+
this
96+
#endif
97+
IDictionary<TKey, TValue> list
98+
) where TKey : notnull => new(list);
99+
}
100+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
using System.Collections.ObjectModel;
2+
using System.Runtime.CompilerServices;
3+
4+
[assembly: TypeForwardedTo(typeof(ReadOnlyDictionary<,>))]

0 commit comments

Comments
 (0)