Skip to content

[API Proposal]: ImmutableArray.CreateUnsafe<T>(T[] array) #83141

@Sergio0694

Description

@Sergio0694

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):

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions