通用列表是连续存储在内存中的

gon*_*ing 2 .net c# c++-cli

有各种文章,例如msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx,这似乎表明通用List的项目存储在连续的内存中.但无论如何,我无法找到任何明确的声明.有谁知道一个.请注意,非常清楚地表明数组是连续的,但此问题适用于List.

还有什么方法可以直接访问List使用的内存?

xan*_*tos 7

List <T>的来源非常明确:

public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{
    private const int _defaultCapacity = 4;

    private T[] _items;
Run Code Online (Sandbox Code Playgroud)

a List<T>包含一个T(T[])的数组,所以如果数组是连续的(是的,它是),那么List<T>是连续的:-)

并从List <T> MSDN页面:

List类是ArrayList类的通用等价物.它通过使用一个数组来实现IList泛型接口,该数组的大小根据需要动态增加.

对于第二个问题:

还有什么方法可以直接访问List使用的内存?

你似乎更像是一个"理论"程序员,所以答案是否定的.对于正在阅读本文的"实用"程序员,他们可以使用:

public static class ArrayFromList
{
    public static FieldInfo GetField<T>()
    {
        return ArrayFromListImpl<T>.Field;
    }

    public static T[] GetArray<T>(List<T> list)
    {
        return ArrayFromListImpl<T>.GetArray(list);
    }

    public static class ArrayFromListImpl<T>
    {
        public static readonly FieldInfo Field;

        public static readonly Func<List<T>, T[]> GetArray;

        static ArrayFromListImpl()
        {
            Field = typeof(List<T>)
                .GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                .Where(x => x.FieldType == typeof(T[]))
                .Single();

            var par = Expression.Parameter(typeof(List<T>));
            var exp = Expression.Lambda<Func<List<T>, T[]>>(Expression.Field(par, Field), par);
            GetArray = exp.Compile();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它像:

var lst = new List<int> { 1, 2, 3 };
var ptr = ArrayFromList.GetArray(lst);
Run Code Online (Sandbox Code Playgroud)

请注意,这不适List<T>用于"隐藏"子对象中的数组的"理论" :-)(但可以在.NET和Mono上工作:-))

  • 是的,但这是当前的实现细节,而不是公共接口级别的保证. (3认同)
  • 请注意,如果`T`是引用类型,则句柄在内存中是连续的,但实际对象不是. (3认同)
  • @goneskiing它使用反射来查找一个数组,在Microsoft实现中命名为`_items` :-)然后它使用一些技巧来缓存这个数组访问,这样反射只对每种类型的`List <使用一次T>`,连续使用不使用它.**并记住数组可能比`List <T>`的`Count`大!** (2认同)