列表C#容量始终为0,即使使用具有容量的构造函数?

时间:2015-10-10 06:32:53

标签: c# list generics

给出这个简单的同步代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Mutex
{
    class CalcArrayThreads
    {
        private static System.Threading.Mutex mutex = new System.Threading.Mutex();
        private const int ThreadsNumber = 10;
        private static List<int> list = new List<int>(10);
        public static void SumPartialArray(object index)
        {
            mutex.WaitOne();
            int indexBoxed = (int) index;
            int sum = 0;
            for (int i = indexBoxed; i < indexBoxed + 9; i++)
            {
                sum += i;
            }
             Console.WriteLine(string.Format("Thread : {0} Calculated value : {1}", Thread.CurrentThread.Name, sum));

            // list.Add(sum);
            list[indexBoxed] = sum;
            mutex.ReleaseMutex();        
            // Console.WriteLine(list.Count());
        }
        static void Main(string[] args)
        {
            for (int i = 0; i < ThreadsNumber; i++)
            {
                Thread myThread = new Thread(new ParameterizedThreadStart(SumPartialArray));
                myThread.Name = String.Format("Thread{0}", i + 1);
                myThread.Start(i);
            }
            Console.Read();
        }
    }
}

当我使用该行时:

list[indexBoxed] = sum;

我明白了:

  

未处理的异常:System.ArgumentOutOfRangeException:索引已经失效   范围。必须是非负的且小于的大小   集合。

即使列表的容量是10。

为什么?

3 个答案:

答案 0 :(得分:2)

由于您尚未向列表中添加任何内容。它始终是0

您实际上需要使用Count属性来获取列表中的元素数量。

来自MSDN的评论:

  

容量是List之前可以存储的元素数   需要调整大小,而Count是元素的数量   实际上在列表中。

     

容量始终大于或等于计数。如果计数超过   添加元素时的容量,容量增加了   在复制旧数据之前自动重新分配内部数组   元素和添加新元素。

答案 1 :(得分:2)

如果您只是使用数组执行以下操作,它将按预期工作,设置第二个元素:

int[] list = new int[10];

list[2] = 5;  // second element is 5, no exception thrown

查看List<T>构造函数,当您传入容量时,它实际上使用内部数组执行非常相似的操作:

this._items = new T[capacity];

因此,当你尝试访问任何低于容量的元素时,它似乎应该工作,但是这里是如何实现索引器的:

public T this[int index]
{
    get
    {
        if (index >= this._size)
            throw new ArgumentOutOfRangeException("...");
        return this._items[index];
    }
    set
    {
        if (index >= this._size)
            throw new ArgumentOutOfRangeException("...");
        this._items[index] = value;
    }
}

它实际上首先检查_size变量,如果您请求的index大于它,则抛出异常。如果不是那张支票,那么它就像你期望的那样工作。

_size初始化为0,除非您将非空集合传递给构造函数,并在使用AddRemoveAtClear等时更改值方法。在内部,它仍然只是使用数组来存储元素,如果_size大于容量(比如,在尝试Add一个元素之后),它会分配一个新数组并将旧(较小)数组中的所有元素复制到其中。

我看到了您可以考虑使用的两种解决方案:

要么只使用一个数组,就像这样:

private static int[] list = new int[10];

或者通过构造函数提供一些默认值的集合(这里是一堆零):

private static List<int> list = new List<int>(Enumerable.Repeat(0, 10));

答案 2 :(得分:0)

您在构造函数中传递的值是初始容量,然后随着列表的增长动态增加。

但是清单仍然是空的。在空列表中使用索引访问器将产生您所看到的确切异常。

要向列表添加元素,请使用Add方法,而不要担心容量。它在内部发展。

编辑:关于你问题的标题,我相信Count总是0(你没有添加元素)而不是容量。