-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
There are several scenarios where it's useful to create an ImmutableArray<T> value over an existing array that's been pre-populated, which the caller owns. But, there is no way of creating such an ImmutableArray<T> value without doing an extra copy and/or allocating a new array. This is not ideal in cases where callers do own the existing array and just want to wrap it and transfer ownership. A common approach is to rely on the internals of ImmutableArray<T> and do something like this:
Foo[] items = new Foo[numberOfItems];
PopulateItems(items);
ImmutableArray<Foo> array = Unsafe.As<Foo[], ImmutableArray<Foo>>(ref items);This works fine today, as the layout of ImmutableArray<T> does match that of T[], but it's far from ideal and generally undefined behavior. This proposal is about adding a reliable API to just allow advanced users to do this in a safe and reliable way.
API Proposal
namespace System.Runtime.InteropServices;
public static class ImmutableCollectionsMarshal
{
public static ImmutableArray<T> AsImmutableArray<T>(T[]? array);
public static T[]? AsArray<T>(ImmutableArray<T> array);
}API Usage
Here's the previous example, rewritten using this API:
Foo[] items = new Foo[numberOfItems];
PopulateItems(items);
ImmutableArray<Foo> array = ImmutableCollectionsMarshal.AsImmutableArray(items);Here's some current uses of this (some of them are in 1st party libraries as well):
- microsoft/clrmd
- stronginject
- ComputeSharp (and also here)
Risks
No risk, as people are already doing this using Unsafe.As, which is undefined behavior. The new API would allow them to keep the same performance characteristics while making the code safe and reliable. The method would have the "Unsafe" suffix which is now an established pattern for these kind of APIs, so non advanced users would clearly see it as not something they should use.