Open pranavkm opened 3 years ago
Tagging subscribers to this area: @eiriktsarpalis See info in area-owners.md if you want to be subscribed.
Author: | pranavkm |
---|---|
Assignees: | - |
Labels: | `api-suggestion`, `area-System.Linq`, `untriaged` |
Milestone: | - |
Given that this could allow violating some internal invariants of the underlying collection, this should not be an extension method. If added, it should probably go on CollectionsMarshal
. See also https://github.com/dotnet/runtime/issues/27061.
Currently CollectionMarshal
is restricted to accessing storage internals of concrete data types. I'm not sure how I feel about extending this to an interface: we'd basically be supporting a handful of known implementations and returning false for everything else.
Tagging subscribers to this area: @eiriktsarpalis See info in area-owners.md if you want to be subscribed.
Author: | pranavkm |
---|---|
Assignees: | - |
Labels: | `api-needs-work`, `api-suggestion`, `area-System.Collections` |
Milestone: | - |
What about having this directly in the interface? Something like:
public interface IEnumerable<out T>
{
public bool TryGetSpan(out ReadOnlySpan<T> span)
{
span = default;
return false;
}
}
Then any implementation of IEnumerable<T>
could also have an implementation for this if it wishes and can.
Adding DIMs to existing interfaces (particularly very popular ones) can introduce both source and runtime breaking changes due to the potential of diamond ambiguities arising in type hierarchies. See this repo for an example.
Adding DIMs to existing interfaces (particularly very popular ones) can introduce both source and runtime breaking changes due to the potential of diamond ambiguities arising in type hierarchies. See this repo for an example.
This makes me sad. I thought the primary use case for DIMs was to allow non-breaking evolution for interfaces. In my opinion, adding such functionality in utility classes such as CollectionsMarshal
is not good for the community and library authors, as such functionality will be restricted to the BCL only.
@eiriktsarpalis why future? Is that .NET 7?
We could consider it for inclusion in .NET 7, but as it stands the proposed design has a few issues in my view:
IEnumerable<T>
when in reality it is only supporting a handful of know concrete collection types (likely only very popular ones living in System.Private.CoreLib). This could violate user expectations (who may for example expect CopyTo
-like semantics for things that implement ICollection<T>
).CollectionsMarshal
methods that act on concrete collections. If anything, it might be better since it lets them focus specifically in the collection types they are interested in:
bool MyTryGetSpan(this IEnumerable<T> source, out ReadOnlySpan<T> ros)
{
if (source is T[] arr)
{
ros = arr;
return true;
}
if (source is List<T> list)
{
ros = CollectionsMarshal.GetSpan(list);
return true;
}
if (source is MyCollection<T> myColl)
{
// some other collection type defined in a user application
ros = myColl._buffer;
return true;
}
}
Background and motivation
A number of APIs expose or consume an
IEnumerable<T>
which are often backed by aList<T>
or an array. A motivated user might want to avoid theGetEnumerator
allocation in these cases. It would be nice ifEnumerable
provided an API similar toTryGetNonEnumeratedCount
to get at the backingspan
for allocation free enumerationAPI Proposal
API Usage
Risks
n/a