Skip to content

[Api Proposal] Add List<T> AsSpan to CollectionsMarshal #27061

Closed
dotnet/coreclr
#26867

Description

@benaadams

Its not a "safe" operation, though it is a useful one to gain access to the prebuilt array; without first copying using .ToArray()

namespace System.Runtime.InteropServices
{
    public partial static class CollectionsMarshal
    {
        public Span<T> AsSpan(List<T> list);
        public Memory<T> AsMemory(List<T> list);
    }
}

/cc @jkotas

Activity

  1. changed the title [-]Add List<T>.AsSpan to MemoryMarshal [/-] [+][Api Proposal] Add List<T>.AsSpan to MemoryMarshal [/+] on Aug 4, 2018
  2. jkotas commented on Aug 4, 2018

    @jkotas
    Member

    I do not think this should be on MemoryMarshal. This should be on a new one, like CollectionsMarshal.

    This should not be an extension method. No other methods on *Marshal are extension methods to make you do more typing.

    The PowerCollections in corefxlab would be a good place to experiment with this: dotnet/corefxlab#2406

  3. changed the title [-][Api Proposal] Add List<T>.AsSpan to MemoryMarshal [/-] [+][Api Proposal] Add List<T>.AsSpan to CollectionsMarshal[/+] on Aug 4, 2018
  4. benaadams commented on Aug 4, 2018

    @benaadams
    MemberAuthor

    Updated

    The PowerCollections in corefxlab would be a good place to experiment with this

    Would then need to go via private reflection?

  5. danmoseley commented on Aug 15, 2018

    @danmoseley
    Contributor

    @jkotas is reflection what you have in mind?

    @benaadams curious, do you happen to have a motivating scenario?

  6. benaadams commented on Aug 15, 2018

    @benaadams
    MemberAuthor

    curious, do you happen to have a motivating scenario?

    List<T> is a very convenient datastructure for creating an array of an unknown size. However, to use it as an array you need to copy the entire contents again with .ToArray().

    AsSpan/AsMemory would give the "array" correctly bounded (size of List rather than size of backing array); without the copy.

  7. jkotas commented on Aug 15, 2018

    @jkotas
    Member

    @jkotas is reflection what you have in mind?

    I had in mind all the different list and array builders in "Common". They are all variants of List with different performance characteristics.

  8. benaadams commented on Aug 15, 2018

    @benaadams
    MemberAuthor

    All internal though 😢

  9. morganbr commented on Aug 15, 2018

    @morganbr
    Contributor

    Would it make sense to propose a "ListBuilder"/"SpanBuilder" type then? It could have roughly the same surface area as List, along with an AsSpan/AsMemory method. Once those are called, mutation is no longer allowed.

  10. danmoseley commented on Aug 15, 2018

    @danmoseley
    Contributor
  11. danmoseley commented on May 30, 2019

    @danmoseley
    Contributor

    @safern this does not seem to me essential in order to ship 3.0. Please correct me if I'm wrong.

  12. Gnbrkm41 commented on Aug 2, 2019

    @Gnbrkm41
    Contributor

    any updates, just wondering? Sounds like a great API 😃

  13. terrajobst commented on Aug 27, 2019

    @terrajobst
    Contributor

    @benaadams We understand that this a logical extension of the current implementation of the type. Could you list some compelling scenarios? We can always come up with potential scenarios.

  14. benaadams commented on Aug 27, 2019

    @benaadams
    MemberAuthor

    Creating a Memory/Span (Array-like) of an unknown upfront size. List<T> is currently the main builder type; but getting an array from it .ToArray() causes a secondary allocation.

    The alternative would be to expose an alternative builder type https://github.com/dotnet/corefx/issues/31597#issuecomment-413059736

  15. TylerBrinkley commented on Aug 27, 2019

    @TylerBrinkley
    Contributor

    FYI, it's currently being discussed here.

  16. Gnbrkm41 commented on Aug 27, 2019

    @Gnbrkm41
    Contributor

    I missed this when I had a list and wanted to do something (been a while... can't remember what the exact situation was) which could be vectorised (since you need to take pointer of the underlying array). It didn't have to be exposed as a Span... but just my thought.

  17. changed the title [-][Api Proposal] Add List<T>.AsSpan to CollectionsMarshal[/-] [+][Api Proposal] Add List<T> AsSpan to CollectionsMarshal[/+] on Aug 31, 2019
  18. terrajobst commented on Sep 24, 2019

    @terrajobst
    Contributor

    Video

    Approved shape:

    namespace System.Runtime.InteropServices
    {
        public partial static class CollectionsMarshal
        {
            public static Span<T> AsSpan(List<T> list);
            public static ReadOnlySpan<T> AsReadOnlySpan(List<T> list);
    
            // We don't want this one:
            // public Memory<T> AsMemory(List<T> list);
        }
    }
  19. ahsonkhan commented on Sep 25, 2019

    @ahsonkhan
    Contributor

    Re-opening until API is exposed from the ref assembly.

  20. eerhardt commented on Sep 25, 2019

    @eerhardt
    Member

    The “approved shape” wasn’t completely implemented with dotnet/coreclr#26867. Should we update the “approved shape” above so it is in sync with the code?

  21. ahsonkhan commented on Sep 26, 2019

    @ahsonkhan
    Contributor

    Re-flagging as api-ready-for-review to address the AsReadOnlySpan change and also do a quick review on the nullable annotations change (see dotnet/coreclr#26903).

    namespace System.Runtime.InteropServices
    {
        public partial static class CollectionsMarshal
        {
            // Updated with nullable annotation
            public static Span<T> AsSpan(List<T>? list);
       
            // Since the AsSpan(...) overload is no longer changing the internal version,
            // we don't need this one anymore
            // public static ReadOnlySpan<T> AsReadOnlySpan(List<T> list);
    
            // We don't want this one:
            // public Memory<T> AsMemory(List<T> list);
        }
    }
  22. terrajobst commented on Oct 1, 2019

    @terrajobst
    Contributor

    Video

    We decided to not increment the version, which is why we removed the AsReadOnlySpan() overload.

    namespace System.Runtime.InteropServices
    {
        public partial static class CollectionsMarshal
        {
            public static Span<T> AsSpan(List<T>? list);
        }
    }
  23. transferred this issue fromdotnet/corefxon Jan 31, 2020
  24. added this to the 5.0 milestone on Jan 31, 2020
  25. ghost locked as resolved and limited conversation to collaborators on Dec 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions