从数组创建列表的效率

时间:2019-01-24 18:14:39

标签: c# arrays .net list type-conversion

我需要从刚刚创建的数组开始创建列表,并且只会将其转换为列表。因此,我可以不复制而将数组利用到列表中,但可以复制the constructor makes a copy。我什至可以理解这样做的动机。但是,在某些情况下,我可以保证除了创建数组的位置之外,该数组没有并且将没有对其的引用。

是否有什么方法可以使这种构造更有效并在列表内部使用数组?我知道如果滥用它会有影响。

最明显的例子是获得string.Split()的结果。如果您需要列表,唯一的明显方法就是进行此转换。目前,我不考虑编写直接拆分为列表的方法。

2 个答案:

答案 0 :(得分:2)

据我所知,目前尚无官方方法,但仍可以使用System.Reflection。通过查看List<T>的源代码 .NET Framework 4.7.2 ,两个重要属性是_items_size。也有_version,但是只有当您修改List<T>时,它才会更改。修改有AddAddRangeRemove等,还有ReverseSort。因此,我们假设这与从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);
    }
}

然后设置基础数组

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

list.SetUnderlyingArray(array);

注意:此解决方案高度依赖于实现的详细信息,如果List<T>内部结构发生某些变化,可能会出错,但是可以深入了解如何实现。

注意。 >

答案 1 :(得分:1)

如果您不需要List<T>,则可以创建一个实现IList<T>并且不进行复制的新类。