我需要从刚刚创建的数组开始创建列表,并且只会将其转换为列表。因此,我可以不复制而将数组利用到列表中,但可以复制the constructor makes a copy。我什至可以理解这样做的动机。但是,在某些情况下,我可以保证除了创建数组的位置之外,该数组没有并且将没有对其的引用。
是否有什么方法可以使这种构造更有效并在列表内部使用数组?我知道如果滥用它会有影响。
最明显的例子是获得string.Split()
的结果。如果您需要列表,唯一的明显方法就是进行此转换。目前,我不考虑编写直接拆分为列表的方法。
答案 0 :(得分:2)
据我所知,目前尚无官方方法,但仍可以使用System.Reflection
。通过查看List<T>
的源代码 .NET Framework 4.7.2 ,两个重要属性是_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);
}
}
然后设置基础数组
int[] array = Enumerable.Repeat(1, 1000000).ToArray();
List<int> list = new List<int>();
list.SetUnderlyingArray(array);
注意:此解决方案高度依赖于实现的详细信息,如果List<T>
内部结构发生某些变化,可能会出错,但是可以深入了解如何实现。
答案 1 :(得分:1)
如果您不需要List<T>
,则可以创建一个实现IList<T>
并且不进行复制的新类。