Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
46 changes: 23 additions & 23 deletions apiCount.include.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
**API count: 956**
**API count: 959**

### Per Target Framework

| Target | APIs |
| -- | -- |
| `net461` | 932 |
| `net462` | 932 |
| `net47` | 931 |
| `net471` | 930 |
| `net472` | 926 |
| `net48` | 926 |
| `net481` | 926 |
| `netstandard2.0` | 928 |
| `netstandard2.1` | 759 |
| `netcoreapp2.0` | 852 |
| `netcoreapp2.1` | 771 |
| `netcoreapp2.2` | 771 |
| `netcoreapp3.0` | 717 |
| `netcoreapp3.1` | 716 |
| `net5.0` | 588 |
| `net6.0` | 493 |
| `net7.0` | 340 |
| `net8.0` | 222 |
| `net9.0` | 146 |
| `net10.0` | 94 |
| `net11.0` | 57 |
| `uap10.0` | 918 |
| `net461` | 933 |
| `net462` | 933 |
| `net47` | 932 |
| `net471` | 931 |
| `net472` | 927 |
| `net48` | 927 |
| `net481` | 927 |
| `netstandard2.0` | 929 |
| `netstandard2.1` | 760 |
| `netcoreapp2.0` | 853 |
| `netcoreapp2.1` | 772 |
| `netcoreapp2.2` | 772 |
| `netcoreapp3.0` | 718 |
| `netcoreapp3.1` | 717 |
| `net5.0` | 589 |
| `net6.0` | 494 |
| `net7.0` | 341 |
| `net8.0` | 223 |
| `net9.0` | 147 |
| `net10.0` | 95 |
| `net11.0` | 58 |
| `uap10.0` | 919 |
8 changes: 8 additions & 0 deletions api_list.include.md
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,14 @@
* `KeyValuePair<TKey, TValue> Create<TKey, TValue>(TKey, TValue)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair.create?view=net-11.0)


#### CollectionsMarshal

* `Span<T> AsSpan<T>(List<T>?)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.asspan?view=net-11.0)
* Note: Reads the list's private backing array via reflection on this target.
* `void SetCount<T>(List<T>, int)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.setcount?view=net-11.0)
* Note: When growing, new elements are default(T); the BCL exposes uninitialized data.


#### TaskCompletionSource

#### UnreachableException
Expand Down
1 change: 1 addition & 0 deletions src/ApiBuilderTests/BuildApiTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public Task RunWithRoslyn()
WriteHelper("Ensure*", writer, ref count);
WriteHelper("Lock", writer, ref count);
WriteHelper(nameof(KeyValuePair), writer, ref count);
WriteHelper("CollectionsMarshal", writer, ref count);
WriteType(nameof(TaskCompletionSource), writer, ref count);
WriteType(nameof(UnreachableException), writer, ref count);

Expand Down
6 changes: 6 additions & 0 deletions src/Consume/Consume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ class Consume
type = typeof(MatchType);
type = typeof(MatchCasing);

var collectionsMarshalList = new List<int> {1, 2, 3};
CollectionsMarshal.SetCount(collectionsMarshalList, 5);
#if FeatureMemory && !WINDOWS_UWP
var collectionsMarshalSpan = CollectionsMarshal.AsSpan(collectionsMarshalList);
#endif

var (key, value) = KeyValuePair.Create("a", "b");

#if NET6_0_OR_GREATER
Expand Down
91 changes: 91 additions & 0 deletions src/Polyfill/CollectionsMarshal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma warning disable

#if !NET5_0_OR_GREATER

namespace System.Runtime.InteropServices;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

/// <summary>
/// An unsafe class that provides a set of methods to access the underlying data representations of collections.
/// </summary>
[ExcludeFromCodeCoverage]
[DebuggerNonUserCode]
#if PolyUseEmbeddedAttribute
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
#endif
#if PolyPublic
public
#endif
static class CollectionsMarshal
{
#if FeatureMemory && !WINDOWS_UWP

/// <summary>
/// Gets a <see cref="Span{T}"/> view over the data in a list. Items should not be added or removed from the <see cref="List{T}"/> while the <see cref="Span{T}"/> is in use.
/// </summary>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.asspan?view=net-11.0
//Note: Reads the list's private backing array via reflection on this target.
public static Span<T> AsSpan<T>(List<T>? list)
{
if (list == null)
{
return default;
}

var items = (T[]) ItemsAccessor<T>.Field.GetValue(list)!;
return new(items, 0, list.Count);
}

static class ItemsAccessor<T>
{
public static readonly FieldInfo Field = typeof(List<T>)
.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)!;
}

#endif

/// <summary>
/// Sets the count of the <see cref="List{T}"/> to the specified value.
/// </summary>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.setcount?view=net-11.0
//Note: When growing, new elements are default(T); the BCL exposes uninitialized data.
public static void SetCount<T>(List<T> list, int count)
{
if (list == null)
{
throw new ArgumentNullException(nameof(list));
}

if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}

var current = list.Count;
if (count < current)
{
list.RemoveRange(count, current - count);
}
else if (count > current)
{
if (list.Capacity < count)
{
list.Capacity = count;
}

for (var index = current; index < count; index++)
{
list.Add(default!);
}
}
}
}

#else
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))]
#endif
57 changes: 57 additions & 0 deletions src/Polyfill/CollectionsMarshalSetCount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma warning disable

// SetCount was added to the BCL CollectionsMarshal in net8.0, but the type itself
// exists from net5.0. For net5.0-net7.0 the type is present (so it cannot be
// recreated) and SetCount is added as a static extension member. For earlier
// targets SetCount lives on the recreated type in CollectionsMarshal.cs.
#if NET5_0_OR_GREATER && !NET8_0_OR_GREATER

namespace Polyfills;

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

static partial class Polyfill
{
extension(CollectionsMarshal)
{
/// <summary>
/// Sets the count of the <see cref="List{T}"/> to the specified value.
/// </summary>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.setcount?view=net-11.0
//Note: When growing, new elements are default(T); the BCL exposes uninitialized data.
public static void SetCount<T>(List<T> list, int count)
{
if (list == null)
{
throw new ArgumentNullException(nameof(list));
}

if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}

var current = list.Count;
if (count < current)
{
list.RemoveRange(count, current - count);
}
else if (count > current)
{
if (list.Capacity < count)
{
list.Capacity = count;
}

for (var index = current; index < count; index++)
{
list.Add(default!);
}
}
}
}
}

#endif
1 change: 1 addition & 0 deletions src/Split/net10.0/TypeForwardeds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[assembly: TypeForwardedTo(typeof(System.Buffers.Text.Base64Url))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))]
[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute))]
[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.ConfigureAwaitOptions))]
[assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute))]
Expand Down
1 change: 1 addition & 0 deletions src/Split/net11.0/TypeForwardeds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[assembly: TypeForwardedTo(typeof(System.Buffers.Text.Base64Url))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CollectionBuilderAttribute))]
[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.CollectionsMarshal))]
[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute))]
[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.ConfigureAwaitOptions))]
[assembly: TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute))]
Expand Down
72 changes: 72 additions & 0 deletions src/Split/net461/CollectionsMarshal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// <auto-generated />
#pragma warning disable
#pragma warning disable
namespace System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
/// <summary>
/// An unsafe class that provides a set of methods to access the underlying data representations of collections.
/// </summary>
[ExcludeFromCodeCoverage]
[DebuggerNonUserCode]
#if PolyUseEmbeddedAttribute
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
#endif
#if PolyPublic
public
#endif
static class CollectionsMarshal
{
#if FeatureMemory
/// <summary>
/// Gets a <see cref="Span{T}"/> view over the data in a list. Items should not be added or removed from the <see cref="List{T}"/> while the <see cref="Span{T}"/> is in use.
/// </summary>
public static Span<T> AsSpan<T>(List<T>? list)
{
if (list == null)
{
return default;
}
var items = (T[]) ItemsAccessor<T>.Field.GetValue(list)!;
return new(items, 0, list.Count);
}
static class ItemsAccessor<T>
{
public static readonly FieldInfo Field = typeof(List<T>)
.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)!;
}
#endif
/// <summary>
/// Sets the count of the <see cref="List{T}"/> to the specified value.
/// </summary>
public static void SetCount<T>(List<T> list, int count)
{
if (list == null)
{
throw new ArgumentNullException(nameof(list));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
var current = list.Count;
if (count < current)
{
list.RemoveRange(count, current - count);
}
else if (count > current)
{
if (list.Capacity < count)
{
list.Capacity = count;
}
for (var index = current; index < count; index++)
{
list.Add(default!);
}
}
}
}
72 changes: 72 additions & 0 deletions src/Split/net462/CollectionsMarshal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// <auto-generated />
#pragma warning disable
#pragma warning disable
namespace System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
/// <summary>
/// An unsafe class that provides a set of methods to access the underlying data representations of collections.
/// </summary>
[ExcludeFromCodeCoverage]
[DebuggerNonUserCode]
#if PolyUseEmbeddedAttribute
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
#endif
#if PolyPublic
public
#endif
static class CollectionsMarshal
{
#if FeatureMemory
/// <summary>
/// Gets a <see cref="Span{T}"/> view over the data in a list. Items should not be added or removed from the <see cref="List{T}"/> while the <see cref="Span{T}"/> is in use.
/// </summary>
public static Span<T> AsSpan<T>(List<T>? list)
{
if (list == null)
{
return default;
}
var items = (T[]) ItemsAccessor<T>.Field.GetValue(list)!;
return new(items, 0, list.Count);
}
static class ItemsAccessor<T>
{
public static readonly FieldInfo Field = typeof(List<T>)
.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic)!;
}
#endif
/// <summary>
/// Sets the count of the <see cref="List{T}"/> to the specified value.
/// </summary>
public static void SetCount<T>(List<T> list, int count)
{
if (list == null)
{
throw new ArgumentNullException(nameof(list));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
var current = list.Count;
if (count < current)
{
list.RemoveRange(count, current - count);
}
else if (count > current)
{
if (list.Capacity < count)
{
list.Capacity = count;
}
for (var index = current; index < count; index++)
{
list.Add(default!);
}
}
}
}
Loading
Loading