C# 如何预分配T列表中的C列表

C# 如何预分配T列表中的C列表,c#,list,multidimensional-array,pre-allocation,C#,List,Multidimensional Array,Pre Allocation,我想预先分配一份名单。我知道我可以像这样预先分配一维列表: List<double> MyList = new List<double>(SomeSize); 是否可以对嵌套列表执行此操作?在C++中,我会这样做: vector<vector<double>> MyList(OuterSize, vector<double>(InnerSize)); 在C语言中,我似乎找不到一种有效的方法来实现这一点,但我确信有一种方法 没有这种方

我想预先分配一份名单。我知道我可以像这样预先分配一维列表:

List<double> MyList = new List<double>(SomeSize);
是否可以对嵌套列表执行此操作?在C++中,我会这样做:

vector<vector<double>> MyList(OuterSize, vector<double>(InnerSize));

在C语言中,我似乎找不到一种有效的方法来实现这一点,但我确信有一种方法

没有这种方法,因为它不是一段连续的内存。你必须自己编程——迭代外部维度

一个列表并不能与C++数组相比。您为它分配内存,这意味着您避免了列表的增长,但是列表以Count=0开始,并且您必须添加元素,您无法通过索引器访问它。 并且具有容量的初始化是可选的!如果您提前知道最终长度,这只会稍微提高性能

如果使用固定长度数组,则可以分配多维数组 像


立即。

预先分配列表的唯一方法是实例化它。您当然可以实例化外部列表,但是如果您想预分配内部列表,您也必须实例化它们,这意味着您必须预填充外部列表

你可以用

var list = Enumerable.Range(1, OuterSize)
     .Select( x => new List<T>(InnerSize) )
     .ToList();

实例化OutListSnple元素的列表,每个元素都是内层元素的列表,所有元素都具有相同的NULL /默认值。

< P> C++代码使用vector的填充构造函数,它实例化集合的第一维的所有元素,并表示第二维度的列表。

C列表对象没有允许指定初始容量的填充构造函数。现有的填充构造函数保证列表将有足够的容量容纳IEnumerable参数提供的项,但不能保证容量与参数enumerable的基数紧密匹配,部分原因是enumerable在设计上不会公开其基数,因此,与容量完全匹配的唯一方法是每次调整列表底层数组的一个元素的大小

通过构造所需容量的空列表,然后添加第二维度的对象,每个对象都初始化为其所需容量,可以用一个小Linq在两行中完成此操作,用传统循环在三行中完成此操作:

var myList = new List<List<T>>(5);
//Option A: Linq
myList.AddRange(Enumerable.Repeat(0, 5).Select(x => new List<string>(4)));
//Option B: Loop
for(i=0;i<5;i++)
    myList.Add(new List<string>(4));

这做了同样的事情,只是Repeat方法重复的不是垃圾数据,而是对执行对象构造的lambda的引用,然后在Select方法的lambda中调用。但是,我现在有两个lambda,它们被实现为包含此代码的类的私有公式化命名函数,这给结果对象添加了比我们真正需要的更多的粗糙。编译器也无法从lambda语句推断Repeat函数的泛型输出类型,因此上述代码无法编译;我必须显式地指定泛型类型,这行代码和C作为一种语言已经足够详细了。

当您提供这样的初始容量时,列表仍然是空的,因此您仍然需要添加项。您可以在那个时候设置这些列表的初始容量。您只能设置最外层列表的“容量”。您不必担心为列表分配内存。列表本质上是可扩展的,所以与数组不同,您实际上不需要设置容量。这种期望是不正确的。构造函数参数以该大小分配内部数组,但项计数仍然为零。在填充列表之前,不能以这种方式使用ElementAt。听起来你想要一个参差不齐的数组,但绝对不是。如果您没有首先添加元素就这样做,它将抛出一个异常:var list=newlist3;list.ElementAt2;仅供参考,第二个示例中缺少赋值运算符
var list = Enumerable.Range(1, OuterSize)
    .Select
    (
        x => Enumerable.Range(1, InnerSize)
                 .Select( y => default(T) )
                 .ToList()
    )
    .ToList();
var myList = new List<List<T>>(5);
//Option A: Linq
myList.AddRange(Enumerable.Repeat(0, 5).Select(x => new List<string>(4)));
//Option B: Loop
for(i=0;i<5;i++)
    myList.Add(new List<string>(4));
myList.AddRange(Enumerable.Repeat(()=>new List<string>(4), 5).Select(x => x()));