C#數組的使用

來源:互聯網
上載者:User

標籤:它的   safe   存在   item   繼承   nsa   努力   部分   public   

          C#基礎文法中得數組,定義就是:數組是一種資料結構,包含同一個類型的多個元素。從CLR的角度來看,首先數組是參考型別,堆棧分配屬於分配於堆上,其次數組在記憶體中是連續的儲存的,所以索引速度很快,而且賦值與修改元素也很簡單。可以利用位移地址訪問元素,時間複雜度為O(1);可以用折半尋找法尋找元素,效率高。

         上面這段話初看之下很莫名奇妙,解釋一下,首先基礎文法定義了數組是什麼,是一種資料結構,資料結構有很多種:棧,隊列,列表,字典,樹,圖,數組也是這樣一種資料結構,而且是很多其他資料結構的基本,但是數組的內的資料類型只能是一種,在一個數組中不能既存在int又存在string

          數組,ArrayList,List區別

          在從CLR的角度來看,CLR介紹數組時,就從其派生自System.Array,而System.Array派生自Object,所以數組是參考型別,分配於託管堆上,並且數組在託管堆上分配到的是一塊連續儲存的記憶體,可以通過索引尋找,雖然查詢的時間複雜度是O(1),但有個問題被忽略了,就是找的快未必就有用,數組分配在一塊連續的資料空間上,因此分配空間時必須確定大小。空間的連續,也導致了儲存效率低,插入和刪除元素效率比較低,而且麻煩。如果,要增添一個元素,需要移動大量元素,在記憶體中空出一個元素的空間,然後將要增加的元素放在其中。同樣,你想刪除一個元素,需要移動大量元素去填補被移動的元素。這就是數組的詬病,為瞭解決這個問題C#又推出了ArrayList

          ArrayList是.Net Framework提供的用於資料存放區和檢索的專用類,它是命名空間System.Collections下的一部分。它的大小是按照其中儲存的資料來動態擴充與收縮的。所以,我們在聲明ArrayList對象時並不需要指定它的長度。但微軟又發現使用ArrayList存在一個更為致命的問題,看下面的代碼

 1              //初始化ArrayList  2              ArrayList list = new ArrayList(); 3             //新增資料 4             list.Add("abc"); 5             list.Add(123); 6             //插入資料 7             list.Insert(0, "在第一個位置插入一條資料"); 8             foreach (var item in list) 9             {10                 Console.WriteLine(item);11             }
View Code

        在list中,我們不僅插入了字串"abc",而且又插入了數字123。這樣在ArrayList中插入不同類型的資料是允許的。因為ArrayList會把所有插入其中的資料都當作為object類型來處理。這樣,在我們使用ArrayList中的資料來處理問題的時候,很可能會報類型不符的錯誤,也就是說ArrayList不是型別安全的。既使我們保證在插入資料的時候都很小心,都有插入了同一類型的資料,但在使用的時候,我們也需要將它們轉化為對應的原類型來處理。這就存在了裝箱與拆箱的操作,會帶來很大的效能損耗。

        雖然ArrayList解決了數組長度問題,但是留下了型別安全問題,裝箱和拆箱操作一直是操作程式中所努力在避免的操作,因為其對效能的損耗確實是很大的,所以C#推出了Lits集合,下面的代碼是聲明實現一個List的集合,可以看到List指定了類型,避免了拆箱裝箱的操作,並且也無需指定元素個數。

1      List<int> list = new List<int>();2             //新增資料3             list.Add(123);4             //報錯,無法從string轉化成int5             list.Add("123");6             foreach (var item in list)7             {8                 Console.WriteLine(item);9             }
View Code

          事實上,List來自對ArrayList的封裝,而ArrayList封裝自數組,數組是ArrayList和List的底層實現,那麼是不是使用List就可以完美的代替數組了呢?以後所有的代碼都只需要寫成List就好了,既然List是來自數組的封裝,繼承了數組的所有方法和行為,其實這裡有一次回到了效率問題,如果是固定的並且知道其長度的資料集合用數組,而不固定長度的用List。額講了這麼多,或許就是這句話最重要吧。

          建立下限非零的數組

          C#中有兩種數組,一種是下表從0開始的數組,一種是下標非0開始的,不推薦使用下標非0開始的,通過下面的代碼就可以建立一個指定下限的多維陣列

 1   static void Main(string[] args) 2         { 3             // 建立和初始化多維陣列字串類型。 4             int[] myLengthsArray = new int[2] { 3, 5 }; 5             int[] myBoundsArray = new int[2] { 2, 3 }; 6             //CreateInstance  建立指定下標的數組的方法 7             //elementTypeType: System.Type要建立的 Array 的 Type。 8             //一維數組,它包含要建立的 Array 的每個維度大小。 9             //一維數組,它包含要建立的 Array 的每個維度下限(起始索引)。10             Array myArray = Array.CreateInstance(typeof(String), myLengthsArray, myBoundsArray);11 12             for (int i = myArray.GetLowerBound(0); i <= myArray.GetUpperBound(0); i++)13                 for (int j = myArray.GetLowerBound(1); j <= myArray.GetUpperBound(1); j++)14                 {15                     int[] myIndicesArray = new int[2] { i, j };16                     myArray.SetValue(Convert.ToString(i) + j, myIndicesArray);17                 }18 19             //顯示每一個維度上限和下限20             Console.WriteLine("Bounds:\tLower\tUpper");21             for (int i = 0; i < myArray.Rank; i++)22                 Console.WriteLine("{0}:\t{1}\t{2}", i, myArray.GetLowerBound(i), myArray.GetUpperBound(i));23             // 顯示的值的數組。24             Console.WriteLine("The Array contains the following values:");25             PrintValues(myArray);26         }27         public static void PrintValues(Array myArr)28         {29             IEnumerator myEnumerator = myArr.GetEnumerator();30             int i = 0;31             int cols = myArr.GetLength(myArr.Rank - 1);32             while (myEnumerator.MoveNext())33             {34                 if (i < cols)35                 {36                     i++;37                 }38                 else39                 {40                     Console.WriteLine();41                     i = 1;42                 }43                 Console.Write("\t{0}", myEnumerator.Current);44             }45             Console.WriteLine();46         }
View Code

 

        數組的傳遞和返回

            其實傳遞就是當作參數傳遞給函數,返回就是可以作為類型返回接收,但有個問題,數組是參考型別,開篇我們就介紹了,傳遞給函數,如果函數改動了數組,原數組就會跟著一起變,這肯定不是我們想要的。解決方案是可以直接複製一個數組,通過Array.Copy()方法,複製一個新的數組傳遞給函數體,如果不希望原數組被改動的話。

 

        不安全的數組訪問

         我們每次訪問一個數組中的元素時,CLR都會確保索引不會超出數組的上下限。CLR的索引檢查會有一些效能方面的代價。如果大家對自己的代碼有足夠的信心,並且不介意使用非安全的程式碼,則可在訪問一個數組時不讓CLR執行索引檢查。

 1 //unsafe 開啟不安全訪問標誌 2 //需要在你的項目屬性頁面裡面,把是否包含unsafe代碼的選項選上  3 //否則會報錯 4 unsafe static void main() 5 { 6     Int32[] arr = new Int32{1, 2, 3, 4, 5}; 7     //擷取一個指向數組第0元素的指標 8     fixed(Int32 * element = &arr[0]) 9     {10         for(Int32 x = 0, n = arr.Length; x < n; x++)11         {12             Console.WriteLine(element[x]);13         }14     }15 }
View Code

 

 

          小結

           今天的內容理論偏多代碼偏少,因為關於數組我覺得以CLR的角度看,不需要寫聲明,增刪查,二維多維陣列這些概念,還有數組的排序和複製,如果把數組的一個一個方法拿出來介紹可能並沒有多少必要性,而是分析一下數組在底層是一個怎樣的分配,它和ArrayList還有List是什麼關係,其實數組可以說是很多資料結構的基礎。

          

C#數組的使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.