在c#中,数组列表和List<>有什么区别?

是不是只有List<>有类型而ArrayList没有?


当前回答

性能已经在几个答案中被提到作为一个区分因素,但是要解决“数组列表有多慢?”和“为什么整体上更慢?”,请看下面的内容。

当使用值类型作为元素时,ArrayList的性能会急剧下降。考虑简单地添加元素的情况。由于装箱正在进行——因为ArrayList的Add只接受对象参数——垃圾收集器被触发执行比List<T>更多的工作。

时差是多少?至少比List<T>慢几倍。看看在数组列表中添加10mil int值和List<T>的代码会发生什么:

在“均值”列(黄色突出显示)中,这是5倍的运行时间差异。还要注意为每个gc执行的垃圾收集数量的差异,用红色突出显示(每1000次运行没有gc)。

使用分析器快速查看发生了什么,这表明大部分时间都花在了gc上,而不是实际添加元素。下面的棕色条表示阻塞垃圾收集器活动:

我在这里https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/写了一篇关于上述ArrayList场景的详细分析。

Jeffrey Richter的《CLR via c#》中也有类似的发现。第12章(泛型):

[…] When I compile and run a release build (with optimizations turned on) of this program on my computer, I get the following output. 00:00:01.6246959 (GCs= 6) List<Int32> 00:00:10.8555008 (GCs=390) ArrayList of Int32 00:00:02.5427847 (GCs= 4) List<String> 00:00:02.7944831 (GCs= 7) ArrayList of String The output here shows that using the generic List algorithm with the Int32 type is much faster than using the non-generic ArrayList algorithm with Int32. In fact, the difference is phenomenal: 1.6 seconds versus almost 11 seconds. That’s ~7 times faster! In addition, using a value type (Int32) with ArrayList causes a lot of boxing operations to occur, which results in 390 garbage collections. Meanwhile, the List algorithm required 6 garbage collections.

其他回答

使用List<T>可以防止强制转换错误。它对于避免运行时强制转换错误非常有用。

例子:

在这里(使用ArrayList),您可以编译这段代码,但稍后会看到一个执行错误。

ArrayList array1 = new ArrayList();
array1.Add(1);
array1.Add("Pony"); //No error at compile process
int total = 0;
foreach (int num in array1)
{
 total += num; //-->Runtime Error
}

如果使用List,可以避免以下错误:

List<int> list1 = new List<int>();
list1.Add(1);
//list1.Add("Pony"); //<-- Error at compile process
int total = 0;
foreach (int num in list1 )
{
 total += num;
}

参考: MSDN

ArrayList是不同类型数据的集合,而List<>是其自身依赖的相似类型数据的集合。

使用“List”可以防止强制转换错误。它对于避免运行时强制转换错误非常有用。

例子:

在这里(使用ArrayList),您可以编译这段代码,但稍后会看到一个执行错误。

    // Create a new ArrayList


    System.Collections.ArrayList mixedList = new System.Collections.ArrayList();


    // Add some numbers to the list
    mixedList.Add(7);
    mixedList.Add(21);


    // Add some strings to the list
    mixedList.Add("Hello");
    mixedList.Add("This is going to be a problem");




    System.Collections.ArrayList intList = new System.Collections.ArrayList();
    System.Collections.ArrayList strList = new System.Collections.ArrayList();


    foreach (object obj in mixedList)
    {
        if (obj.GetType().Equals(typeof(int)))
        {
            intList.Add(obj);
        }
        else if (obj.GetType().Equals(typeof(string)))
        {
            strList.Add(obj);
        }
        else
        {
            // error.
        }
    }

To me its all about knowing your data. If I am continuing to expand my code on the basis of efficiency, I would have to choose the List option as a way of deciphering of my data w/o the unnecessary step of always wondering about types, especially 'Custom Types'. If the machine understands the difference and can determine on it's on what type of data I'm actually dealing with then why should I get in the way and waste time going thru the gyrations of 'IF THEN ELSE' determinations? My philosophy is to let the machine work for me instead of me working on the machine? Knowing the unique differences of different object code commands goes a long way in making your code as efficient.

汤姆•约翰逊 (一项…一个出口)

性能已经在几个答案中被提到作为一个区分因素,但是要解决“数组列表有多慢?”和“为什么整体上更慢?”,请看下面的内容。

当使用值类型作为元素时,ArrayList的性能会急剧下降。考虑简单地添加元素的情况。由于装箱正在进行——因为ArrayList的Add只接受对象参数——垃圾收集器被触发执行比List<T>更多的工作。

时差是多少?至少比List<T>慢几倍。看看在数组列表中添加10mil int值和List<T>的代码会发生什么:

在“均值”列(黄色突出显示)中,这是5倍的运行时间差异。还要注意为每个gc执行的垃圾收集数量的差异,用红色突出显示(每1000次运行没有gc)。

使用分析器快速查看发生了什么,这表明大部分时间都花在了gc上,而不是实际添加元素。下面的棕色条表示阻塞垃圾收集器活动:

我在这里https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/写了一篇关于上述ArrayList场景的详细分析。

Jeffrey Richter的《CLR via c#》中也有类似的发现。第12章(泛型):

[…] When I compile and run a release build (with optimizations turned on) of this program on my computer, I get the following output. 00:00:01.6246959 (GCs= 6) List<Int32> 00:00:10.8555008 (GCs=390) ArrayList of Int32 00:00:02.5427847 (GCs= 4) List<String> 00:00:02.7944831 (GCs= 7) ArrayList of String The output here shows that using the generic List algorithm with the Int32 type is much faster than using the non-generic ArrayList algorithm with Int32. In fact, the difference is phenomenal: 1.6 seconds versus almost 11 seconds. That’s ~7 times faster! In addition, using a value type (Int32) with ArrayList causes a lot of boxing operations to occur, which results in 390 garbage collections. Meanwhile, the List algorithm required 6 garbage collections.