The difference between array, ArrayList and List in c# [transfer]

First explain the Array class in C#: The Array class is the base class for all arrays in C#, and it is defined in the System namespace. The Array class provides various properties and methods for arrays. For some properties and methods of the Array class, see the blog post: HashTable and Array classes in C#: http://www.cnblogs.com/newcapecjmc/p/7099947.html

 

In C#, arrays, ArrayLists, and Lists can all store a set of objects, so what is the difference between the three?
(1) The namespace introduced by the array: using System ;
(2) Array: The usage is basically the same as that of the array, and the namespace is introduced: using System ;
(3) ArrayList: Introduce namespace: using System.Collections
(4) List: Introduce namespace: using System . Collections . Generic ;

array

    Arrays first appeared in C#. It is stored contiguously in memory, so its indexing speed is very fast, and assigning and modifying elements is also very simple.

  1. <span style="font-family: SimSun; font-size: 18px;">//数组  
  2. string[] s=new string[2];  
  3.   
  4. //assign  
  5. s[0]="a";  
  6. s[1]="b";  
  7. //Revise  
  8. s[1]="a1";  
  9. </span>  
//array
string[] s=new string[2];

//assign
s[0]="a";
s[1]="b";
//Revise
s[1]="a1";

 

    But arrays have some shortcomings. It is very troublesome to insert data between the two data of the array, and the length of the array must be specified when declaring the array. If the length of the array is too long, it will cause a waste of memory, and over-segmentation will cause data overflow errors. If we don't know the length of the array when declaring the array, it becomes troublesome.

    For these shortcomings of arrays, C# first provided the ArrayList object to overcome these shortcomings.

ArrayList

    ArrayList is namespace "font-family: SimSun; font-size: 18px;"> //ArrayList  

  • ArrayList list1 = new ArrayList();  
  •   
  • //add data  
  • list1.Add("cde");  
  • list1.Add(5678);  
  •   
  • //change the data  
  • list[2] = 34;  
  •   
  • // remove data  
  • list.RemoveAt(0);  
  •   
  • //insert data  
  • list.Insert(0, "qwe");  
  • </span>  
//ArrayList
ArrayList list1 = new ArrayList();

//add data
list1.Add("cde");
list1.Add(5678);

//change the data
list[2] = 34;

// remove data
list.RemoveAt(0);

//insert data
list.Insert(0, "qwe");

    From the above example, ArrayList seems to solve all the shortcomings of the array, why there is a List?

    As we can see from the above example, in List, we not only inserted the string cde, but also the number 5678. Inserting different types of data in the ArrayList is allowed. Because ArrayList will treat all the data inserted into it as object type, when we use ArrayList to process data, it is likely to report a type mismatch error, that is, ArrayList is not type-safe. Boxing and unboxing operations typically occur when storing or retrieving value types, with significant performance penalties.

    The concept of boxing and unboxing: Simply put: boxing: is to pack the data of the value type into the instance of the reference type, such as assigning the value of the string type abc to the object object obj   

  1. <span style="font-family: SimSun; font-size: 18px;">String  i=”abc”;  
  2. object obj=(object)i;  
  3. </span>  
String  i=”abc”;
object obj=(object)i;

    拆箱:就是从引用数据中提取值类型     比如将object对象obj的值赋给string类型的变量i

  1. <span style="font-family: SimSun; font-size: 18px;">object obj=”abc”;  
  2. string i=(string)obj;  
  3. </span>  
object obj=”abc”;
string i=(string)obj;

    装箱与拆箱的过程是很损耗性能的。

补充:

Array的用法与数组几乎一样,可以看做是数组。在定义的时候需要指定长度;ArrayList的用法与普通集合一样,定义的时候不需要指定长度;
如:Array[] animalArray = new Array[2];
    ArrayList animalArrayList = new ArrayList();

 

 泛型List

    因为ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。

比如:

  1. <span style="font-family: SimSun; font-size: 18px;">List<string> list = new List<string>();  
  2.   
  3. //新增数据  
  4. list.Add(“abc”);  
  5.   
  6. //修改数据  
  7. list[0] = “def”;  
  8.   
  9. //移除数据  
  10. list.RemoveAt(0);  
  11. </span>  
List<string> list = new List<string>();

//新增数据
list.Add(“abc”);

//修改数据
list[0] = “def”;

//移除数据
list.RemoveAt(0);

    上例中,如果我们往List集合中插入int数组123,IDE就会报错,且不能通过编译。这样就避免了前面讲的类型安全问题与装箱拆箱的性能问题了。

补充:

总结:

    数组的容量是固定的,您只能一次获取或设置一个元素的值,而ArrayList或List<T>的容量可根据需要自动扩充、修改、删除或插入数据。

    数组可以具有多个维度,而 ArrayList或 List< T> 始终只具有一个维度。但是,您可以轻松创建数组列表或列表的列表。特定类型(Object 除外)的数组 的性能优于 ArrayList的性能。 这是因为 ArrayList的元素属于 Object 类型;所以在存储或检索值类型时通常发生装箱和取消装箱操作。不过,在不需要重新分配时(即最初的容量十分接近列表的最大容量),List< T> 的性能与同类型的数组十分相近。

    在决定使用 List<T> 还是使用ArrayList 类(两者具有类似的功能)时,记住List<T> 类在大多数情况下执行得更好并且是类型安全的。如果对List< T> 类的类型T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型T使用值类型,则需要考虑实现和装箱问题。

 

 

数组:(1)在声明数组时必须指定数组的大小,过长浪费内存,过短内存溢出(2)在数组中的两个数之间插入数据比较麻烦。

ArrayList(继承了IList接口):可以插入不同的值类型,在数据检索及存储时存在装箱与拆箱操作,容易带来性能消耗。

List(继承了IList接口):在声明List集合时,我们同时需要为其声明List集合内数据的对象类型,避免了装箱与拆箱动作。

 补充:

list<T>类可表示可通过索引访问的对象的强制类型列表,提供用于对列表进行搜索、排序和操作的方法。

 作用:泛型最常见的用途是泛型集合。

 

List的一般用法:所属命名空间:System.Collection.Generic

public class List<T>:IList<T>,Icollection<T>,IEnumerable<T>,IList,Icollection,Ienumerable

List<T>是ArrayList类的泛型等效类,该类使用大小可按需动态增加的数组实现IList<T>泛型接口。

(1)声明 List<T>mlist = new List<T>();  eg: string[] Arr = {"a","b","c"};      List<string> mlist = new List<string>(Arr);

 

(2)添加一个元素 List.Add(T item)     eg: mlist.Add("d");

 

(3)添加集合元素    eg: string[] Arr2 ={"f","g"."h"};        mlist.AddRange(Arr2);

 

(4)在index位置添加一个元素 Insert(int index,T item)    eg: mlist.Insert(1,"p");

 

(5)遍历List中元素

  foreach(T element in mlist) T的类型与mlist声明时一样      {        Console.WriteLine(element);           }

    eg:     foreach(string s in mlist)           {              Console.WriteLine(s);            }

 

(6)删除元素

    List.Remove(T item) 删除一个值     eg: mlist.Remove("a");

    List.RemoveAt(int index);删除下标为index的元素     eg: mlist.RemoveAt(0);          List.RemoveRange(int index,int count); 下标index开始,删除count个元素     eg:mlist.RemoveRange(3,2);

 

 

(7)判断某个元素是否在该List中

    List.Contains(T item) 返回true或false     eg:     if(mlist.Contains"("g"))        Console.WriteLine("g存在列表中");     else        mlist.Add("g");

 

(8)给List里面元素排序 List.Sort() 默认是元素每一个字母按升序    eg: mlist.Sort();

 

(9)给List里面元素顺序反转 List.Reverse() 可以与List.Sort()配合使用

 

(10)List清空 List.Clear()    eg: mlist.Clear();

(11)获得List中元素数目 List.Count() 返回int值    eg: mlist.count();

 

List进阶,强大方法

 

(1)List.FindAll方法:检索与指定谓词所定义的条件相匹配的所有元素           class program     {        static void Main(stirng[] args)        {          student stu = new student();          stu.Name="arron";          List<student> students= new List<student>();          students.Add(stu);          students.Add(new student("candy"));          FindName myname = new FindName("arron");          foreach(student s in students.FindAll(new Predicate<student>(myname.IsName)))          { Console.WriteLine(s);}        }

    public class student     {        public string Name{get;set;}        public student(){}        public override string ToString()         {             return string.Format("姓名:{0}",Name);          }      }

    public class FindName     {       private string _name;       public FindName(string Name)       {  this._name=Name;}       public bool IsName(student s)        { return (s.Name==_name)?true:false;}     }

 

(2)List.Find方法 搜索与指定谓词所定义的条件相匹配的元素,并返回整个List中的第一个匹配元素

  eg:

    //Predicate是对方法的委托,如果传递给它的对象与委托定义的条件匹配,则该方法返回true,当前List的元素   被逐个传递给Predicate委托,并在List中间前移动,从第一个元素开始,到最后一个元素结束,当找到匹配项   时处理停止

  第一种方法 委托给拉姆达表达式:   eg:        string listFind = mlist.Find(name=>        {           if(name.length>3)              return true;           return false;        });

    第二种方法 委托给一个函数     eg:      public bool ListFind(string name)

        {

            if (name.Length > 3)

            {

                return true;

            }

            return false;

        }

      这两种方法的结果是一样的

 

 

(3) List.FindLast方法  public T FindLast(Predicate<T> match);确定是否 List 中的每个元素都与指定的谓词所定义的条件相匹配。用法与List.Find相同。

(4) List.TrueForAll方法:  确定是否 List 中的每个元素都与指定的谓词所定义的条件相匹配。

 public bool TrueForAll(Predicate<T> match);

 

(5) List.Take(n):  获得前n行 返回值为IEnumetable<T>,T的类型与List<T>的类型一样

E.g.:

IEnumerable<string> takeList=  mList.Take(5);

          foreach (string s in takeList)

          {

              Console.WriteLine("element in takeList: " + s);

          }

       这时takeList存放的元素就是mList中的前5个

 

(6) List.Where方法:检索与指定谓词所定义的条件相匹配的所有元素。跟List.FindAll方法类似。

E.g.:

            IEnumerable<string> whereList = mList.Where(name =>

                {

                    if (name.Length > 3)

                    {

                        return true;

                    }

                    else

                    {

                        return false;

                    }

                });

         foreach (string s in subList)

         {

             Console.WriteLine("element in subList: "+s);

         }

         这时subList存储的就是所有长度大于3的元素

 

 

(7)List.RemoveAll方法:移除与指定的谓词所定义的条件相匹配的所有元素。

public int RemoveAll(Predicate<T> match);

E.g.:

            mList.RemoveAll(name =>

                {

                    if (name.Length > 3)

                    {

                        return true;

                    }

                    else

                    {

                        return false;

                    }

                });

            foreach (string s in mList)

            {

                Console.WriteLine("element in mList:     " + s);

            }

      这时mList存储的就是移除长度大于3之后的元素。

 

 

以下博文参考:

 

  数组、List和ArrayList的区别

  数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单,比如:

string[] s=new string[3];
//赋值 s[0]="a"; s[1]="b"; s[2]="c"; //修改 s[1]="b1";

 

  但是数组也存在一些不足的地方。比如在数组的两个数据间插入数据也是很麻烦的,还有我们在声明数组的时候,必须同时指明数组的长度,数组的长度过长,会造成内存浪费,数组和长度过短,会造成数据溢出的错误。这样如果在声明数组时我们并不清楚数组的长度,就变的很麻烦了。C#中最先提供了ArrayList对象来克服这些缺点。

  ArrayList是.Net Framework提供的用于数据存储和检索的专用类,它是命名空间System.Collections下的一部分。它的大小是按照其中存储的数据来动态扩充与收缩的。所以,我们在声明ArrayList对象时并不需要指定它的长度。ArrayList继承了IList接口,所以它可以很方便的进行数据的添加,插入和移除.比如:

copy code
copy code
ArrayList list = new ArrayList();
//新增数据
 list.Add("abc"); list.Add(123); //修改数据 list[2] = 345; //移除数据 list.RemoveAt(0); //插入数据 list.Insert(0, "hello world");
copy code
copy code

从上面示例看,ArrayList好像是解决了数组中所有的缺点,那么它应该就是完美的了,为什么在C#2.0后又会出现List呢?

  在list中,我们不仅插入了字符串"abc",而且又插入了数字123。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把所有插入其中的数据都当作为object类型来处理。这样,在我们使用ArrayList中的数据来处理问题的时候,很可能会报类型不匹配的错误,也就是说ArrayList不是类型安全的。既使我们保证在插入数据的时候都很小心,都有插入了同一类型的数据,但在使用的时候,我们也需要将它们转化为对应的原类型来处理。这就存在了装箱与拆箱的操作,会带来很大的性能损耗。

装箱与拆箱的概念: 简单的来讲: 装箱:就是将值类型的数据打包到引用类型的实例中 比如将int类型的值123赋给object对象o

                int i=123; object o=(object)i;

                    拆箱:就是从引用数据中提取值类型 比如将object对象o的值赋给int类型的变量i

                object o=123; int i=(int)o;

           装箱与拆箱的过程是很损耗性能的。

  正是因为ArrayList存在不安全类型与装箱拆箱的缺点,所以在C#2.0后出现了泛型的概念。而List类是ArrayList类的泛型等效类。它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。 比如:

copy code
copy code
List<int> list = new List<int>();
//新增数据 list.Add(123); //修改数据 list[0] = 345; //移除数据 list.RemoveAt(0);
copy code
copy code

 

  上例中,如果我们往List集合中插入string字符"hello world",IDE就会报错,且不能通过编译。这样就避免了前面讲的类型安全问题与装箱拆箱的性能问题了。

  同时 List不能被构造,但可以向上面那样为List创建一个引用,而ArrayList就可以被构造。 

List list;     //正确   list=null; 
List list= new List(); // is wrong usage

 

  List list = new ArrayList(); This sentence creates an ArrayList object and traces it back to List. At this point it is a List object, and some properties and methods that ArrayList has but List does not have, it can no longer be used. And ArrayList list=new ArrayList(); Creating an object retains all the properties of ArrayList. 

  Benefits of List Generics: The generics feature shifts the task of type safety from you to the compiler by allowing you to specify a specific type for a generic class or method to operate on. There is no need to write code to detect if the data type is correct because the correct data type is enforced at compile time. Reduces the need for type coercion and the possibility of runtime errors. Generics provide type safety without the added overhead of multiple implementations.

 

"fool me once, shame on you. fool me twice, shame on me.", the translation means "fool me once, you are bad; fool me twice, and I am stupid".
 
Original URL:

https://www.cnblogs.com/newcapecjmc/p/6970220.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324930514&siteId=291194637