-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: ImmutableArray.CreateUnsafe<T>(T[] array) #83141
Comments
Tagging subscribers to this area: @dotnet/area-system-collections Issue DetailsBackground and motivationThere are several scenarios where it's useful to create an 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 API Proposalnamespace System.Collections.Immutable;
public static class ImmutableArray
{
public static ImmutableArray<T> CreateUnsafe<T>(T[] array);
} API UsageHere's the previous example, rewritten using this API: Foo[] items = new Foo[numberOfItems];
PopulateItems(items);
ImmutableArray<Foo> array = Unsafe.As<Foo[], ImmutableArray<Foo>>(ref items); Here's some current uses of this (some of them are in 1st party libraries as well):
RisksNo risk, as people are already doing this using
|
@stephentoub forgot about that one, thank you! The issue doesn't seem to be resolved though. The API that was added since that issue was created is the
It seems to me that point hasn't been fully settled just yet. Yes, that hack currently works and everyone's using it, but:
|
Yes. We told people to depend on internal layout of |
I see, fair enough, thank you! I guess we can keep this open to track updating the docs to make this clearer then 🙂 |
I think we will have hard time to find a good place in the docs to add this information. The API docs are organized by APIs. There is no good API to attach this to and including it in the top level ImmutableArray topic would steer people towards the unsafe pattern. If we want to make the situation better, adding the proper unsafe API seems to be like the best option. |
If we did go with that (which I personally like better than documenting the hack), what API shape would you recommend? As in, does the one being proposed here look fine, or would you rather have it be somewhere else and/or using a different name? |
The original approved API shape that was later withdrawn looked fine to me: dotnet/corefx#196 . We would probably want to call it |
I like the idea of an |
Sure! I've updated the proposal as suggested and also added nullability annotations 🙂 Couple questions:
|
I think "As___" is a good naming convention, although we can debate the final name in API review.
Why would the first method need to accept the array by reference in the first place? It is a reference type anyways. You might want to consider updating the namespace to something prefixed by |
Great! I'll update the proposal then 🙂
I would assume the original proposal did that to try to reduce risk? As in, if the method forces you to pass the array reference by reference and resets it, it can help avoid that array being accidentally accessed again after that method is called. I personally don't think that's really needed, since these APIs are already for advanced users who would know not to do that 🤔
That'd cause the type to be much more accessible to all devs using that namespace just to access the other collection types, is that something we'd want? I guess the idea of putting it into |
Same here. I don't see much value in it given that it can be bypassed trivially. |
Looks good as proposed namespace System.Runtime.InteropServices;
public static class ImmutableCollectionsMarshal
{
public static ImmutableArray<T> AsImmutableArray<T>(T[]? array);
public static T[]? AsArray<T>(ImmutableArray<T> array);
} |
@eiriktsarpalis I see this is assigned to you, but I'm also happy to contribute this. Feel free to assign this to me if you want 😄 |
Happy to hand it over, thanks :-) |
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 anImmutableArray<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 ofImmutableArray<T>
and do something like this:This works fine today, as the layout of
ImmutableArray<T>
does match that ofT[]
, 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
API Usage
Here's the previous example, rewritten using this API:
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.The text was updated successfully, but these errors were encountered: