代码之家  ›  专栏  ›  技术社区  ›  Peter Ruderman

有没有办法创建一个Span<T>或Memory<T>来引用C#中列表<T>的元素?

c#
  •  4
  • Peter Ruderman  · 技术社区  · 5 年前

    显然,我可以间接地这样做(例如首先转换为数组),但我的目标是尽可能避免复制和分配。最后,我要编写一个返回 Memory<T> List<T>

    1 回复  |  直到 5 年前
        1
  •  3
  •   Scott Chamberlain    5 年前

    只要你保证不改变 .Count 在内存上的操作和从不执行任何会导致交换列表的内部数组的操作之间,以下操作将起作用。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    
    namespace SandboxNetStandard
    {
        public static class ListAdapter<T>
        {
            private static readonly FieldInfo _arrayField = typeof(List<T>)
                .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
                .Single(x => x.FieldType == typeof(T[]));
    
            /// <summary>
            /// Converts
            /// <paramref name="listIPromiseToNotChangeTheCountOfAndNotCauseCapacityToChange"/>
            /// to an <see cref="Memory{T}"/>.
            /// </summary>
            /// <param name="listIPromiseToNotChangeTheCountOfAndNotCauseCapacityToChange">
            /// The list to convert.
            ///
            /// On each use of the returned memory object the list must have the same value of
            /// <see cref="List{T}.Count"/> as the original passed in value. Also between calls 
            /// you must not do any action that would cause the internal array of the list to
            /// be swapped out with another array.
            /// </param>
            /// <returns>
            /// A <see cref="Memory{T}"/> that is linked to the passed in list.
            /// </returns>
            public static Memory<T> ToMemory(
                List<T> listIPromiseToNotChangeTheCountOfAndNotCauseCapacityToChange)
            {
                Memory<T> fullArray = (T[]) _arrayField.GetValue(
                        listIPromiseToNotChangeTheCountOfAndNotCauseCapacityToChange);
                return fullArray.Slice(0,
                    listIPromiseToNotChangeTheCountOfAndNotCauseCapacityToChange.Count);
            }
        }
    }