ArrayList vs List<>在c#中

c#中ArrayListList<>的区别是什么?

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

454834 次浏览

是的,差不多。List<T>是一个泛型类。它支持存储特定类型的值,而不将其转换为object或从object转换(当TArrayList情况下的值类型时,这会引起装箱/拆箱开销)。ArrayList简单地存储了object引用。作为一个泛型集合,List<T>实现了泛型IEnumerable<T>接口,并且可以在LINQ中轻松使用(不需要任何CastOfType调用)。

ArrayList属于c#没有泛型的时代。不推荐使用List<T>。你不应该在以. net >= 2.0为目标的新代码中使用ArrayList,除非你必须与使用它的旧API进行接口。

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

使用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;
}
< p >参考: MSDN < / p >

再加上以上几点。在64位操作系统中使用ArrayList占用的内存是在32位操作系统中使用的2倍。同时,泛型列表List<T>将使用比ArrayList低得多的内存。

例如,如果我们在32位中使用19MB的ArrayList,则在64位中需要39MB。但是如果你有一个8MB的32位通用列表List<int>,它在64位只需要8.1MB,这与ArrayList相比相差了481%。

来源:用于基本类型和64位的数组列表与泛型列表

对我来说,重要的是了解你的数据。如果我在效率的基础上继续扩展我的代码,我将不得不选择列表选项作为一种解密我的数据的方式,而不是总是怀疑类型的不必要步骤,特别是“自定义类型”。如果机器能理解其中的差异,并能确定我实际处理的是什么类型的数据,那么我为什么要在“If then ELSE”确定的循环中浪费时间呢?我的哲学是让机器为我工作,而不是我在机器上工作。了解不同目标代码命令之间的独特差异,对于提高代码的效率大有帮助。

< p >汤姆·约翰逊 (一项…一个退出)

使用“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.
}
}

要添加的另一个区别是线程同步。

ArrayList通过Synchronized属性提供了一些线程安全性,该属性返回围绕集合的线程安全包装器。包装器的工作原理是在每次添加或删除操作时锁定整个集合。因此,试图访问集合的每个线程都必须等待轮到自己使用一个锁。这是不可伸缩的,并且对于大型集合可能会导致显著的性能下降。

List<T>不提供任何线程同步;当在多个线程上并发添加或删除项时,用户代码必须提供所有同步。

更多信息在这里.Net框架中的线程同步

ArrayList不是类型安全的,而List<T>是类型安全的。简单:)。

我认为,ArrayListList<T>之间的区别是:

  1. List<T>,其中T为value-type,比ArrayList快。这是 因为List<T>避免装箱/解装箱(其中T是值类型) 许多来源说-通常ArrayList只用于向后 兼容性。(并没有真正的区别,但我认为有 重要的注意)。< /李>
  2. 非泛型的ArrayListList<T>更容易反射
  3. ArrayList具有IsSynchronized属性。所以,这很容易 创建并使用同步的ArrayList。我没有找到List<T>IsSynchronized属性。还要记住,这种类型的同步是相对低效的,msdn):

    var arraylist = new ArrayList();
    var arrayListSyncronized = ArrayList.Synchronized(arraylist
    Console.WriteLine($"syncronized {arraylist.IsSynchronized}");
    Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");
    
    
    var list = new List<object>();
    var listSyncronized = ArrayList.Synchronized(list);
    Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
    Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
    
  4. ArrayList has ArrayList.SyncRoot property which can be used for syncronisation (msdn). List<T> hasn't SyncRoot property, so in the following construction you need to use some object if you use List<T>:

    ArrayList myCollection = new ArrayList();
    lock(myCollection.SyncRoot) //  ofcourse you can use another object for this goal
    {
    foreach (object item in myCollection)
    {
    // ...
    }
    }
    

简单的答案是,

数组列表是非泛型的

  • 它是一个对象类型,因此您可以在其中存储任何数据类型。
  • 可以在数组列表中存储任意值(值类型或引用类型),例如string、int、employee和object。(注意,)
  • 装箱和开箱将会发生。
  • 不类型安全。
  • 它更老。

列表是通用的

  • 它是类型的类型,因此您可以在运行时指定T。
  • 根据声明,您只能存储类型为T的值(字符串或int或employee或object)。(注意或)
  • 装箱和开箱不会发生。
  • 类型安全。
  • 它更新。

例子:

ArrayList arrayList = new ArrayList();
List<int> list = new List<int>();


arrayList.Add(1);
arrayList.Add("String");
arrayList.Add(new object());




list.Add(1);
list.Add("String");                 // Compile-time Error
list.Add(new object());             // Compile-time Error

请阅读微软官方文档: https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/

enter image description here

请注意:在理解区别之前,你应该先了解泛型

如.NET Framework 文档中所述

我们不建议你使用ArrayList类的new 发展。相反,我们建议您使用泛型List<T> 类。ArrayList类被设计用来保存异构类 对象的集合。然而,它并不总是提供最好的 的性能。相反,我们建议如下:

  • 对于异构的对象集合,使用List<Object>(在c#中)或List(Of Object)(在Visual Basic中)类型。
  • 对于对象的同构集合,使用List<T>类。

另见不应该使用非泛型集合

表显示了如何将非泛型集合类型替换为它们的泛型对应

性能已经在几个答案中被提到作为区分因素,但要解决“ArrayList慢了多少?”和“为什么整体上变慢了?”,请看看下面。

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

时差是多少?至少比List<T>慢几倍。看看在ArrayListList<T>中添加10 mil int值的代码会发生什么: enter image description here < / p >

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

使用分析器快速查看发生了什么,显示大部分时间都花在做气相色谱上,而不是实际添加元素。下面的棕色条表示阻塞垃圾收集器活动: enter image description here < / p >

我已经写了关于上面ArrayList场景的详细分析。

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

[…]当我编译并运行发布版本时(已转向优化) 在我的计算机上运行这个程序,我得到以下输出。< / p > < p > 00:00:01.6246959 (GCs= 6) List<Int32> < br > (GCs=390) Int32的数组列表 < br > 00:00:02.5427847 (GCs= 4) List<String>
00:00:02.7944831 (GCs= 7)数组列表的字符串

这里的输出显示 使用Int32类型的泛型List算法是非常重要的 比使用Int32的非泛型ArrayList算法快。在 事实上,的差异是惊人的:1.6秒对近11秒 秒。快了7倍!此外,使用值类型 (Int32)使用ArrayList会导致大量装箱操作发生, 这将导致390次垃圾回收。与此同时,榜单

.算法需要6个垃圾回收