从数组创建列表的效率

Man*_*ero 5 .net c# arrays list type-conversion

我需要从之前创建的数组开始创建一个列表,并且只会转换为列表.所以我可以在不制作副本的情况下将数组利用到列表中,但构造函数会复制.我甚至可以理解这个动机.但是有些情况我可以保证数组没有,除了创建它之外没有引用它.

有没有办法让这个结构更有效,并在列表内部使用数组?我知道如果我误用它会有影响.

最明显的例子就是得到一个结果string.Split().如果您需要一个列表,那么唯一明显的方法就是进行此转换.现在我不打算写一个方法直接拆分成一个列表.

Joh*_*nny 2

据我所知,没有官方方法可以做到这一点,但仍然可以使用System.Reflection. 通过查看.NET Framework 4.7.2的源代码List<T>,两个重要的属性是_items和_size。还有_version一个,但只有当你修改时才会改变List<T>。修饰有Add、AddRange、Remove等,也Reverse有 和Sort。因此,我们假设这与从零IEnumerable<T>处创建列表的操作相同。_version

public static class ListExtensions
{
    public static void SetUnderlyingArray<T>(this List<T> list, T[] array)
    {
        lock (list)
        {
            SetInternalArray(list, array);
            SetInternalArraySize(list, array.Length);
        }
    }

    private static void SetInternalArraySize<T>(this List<T> list, int size)
    {
        var prop = list.GetType().GetField(
            "_size", 
            BindingFlags.NonPublic | BindingFlags.Instance);
        prop.SetValue(list, size);
    }

    private static void SetInternalArray<T>(this List<T> list, T[] array)
    {
        var prop = list.GetType().GetField(
            "_items",
            BindingFlags.NonPublic | BindingFlags.Instance);
        prop.SetValue(list, array);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后设置底层数组

int[] array = Enumerable.Repeat(1, 1000000).ToArray();
List<int> list = new List<int>();

list.SetUnderlyingArray(array);
Run Code Online (Sandbox Code Playgroud)

注意:此解决方案高度依赖于实现的细节,如果内部发生变化,则可能会出错List<T>,但它提供了有关如何完成该解决方案的见解。