首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

深入解析 C# Array 陣列:基礎、分類與效能優化

     編輯:關於C語言

前言

Array 是 .NET 中最基礎的集合結構,雖然語法簡單,但其記憶體配置、型別系統交互與 JIT 編譯器優化策略卻蘊含許多進階細節。本文將從陣列大局觀、零基與非零基陣列、多維與交錯陣列、以及不安全程式碼優化等面向,系統性探討 C# 陣列的核心機制與效能考量。

一、陣列大局觀:參考型別與堆上配置

陣列是參考型別,實例永遠配置在 Managed Heap 上,變數本身僅存放參考指標。元素型別分為實值型別與參考型別:

  • 實值型別元素:陣列建立時會自動依據大小將每個元素初始化為預設值(如 int 為 0,DateTime 為 DateTime.MinValue)。
  • 參考型別元素:陣列僅配置指標陣列(每個 4/8 Bytes),元素初始為 null,需另行 new 實體。
int[] intArr = new int[3];           // {0, 0, 0}
DateTime[] dtArr = new DateTime[3];  // {MinValue, MinValue, MinValue}
string[] strArr = new string[3];     // {null, null, null}

二、零基陣列 vs 非零基陣列

1. 零基陣列(預設)

C# 預設建立的陣列皆為零基(Lower Bound = 0),對應 IL 指令 newarr,JIT 編譯器會進行積極優化:迴圈存取時僅在進入前檢查一次邊界,後續不再重複檢查,效能極高。

2. 非零基陣列

透過 Array.CreateInstance 可建立任意下限的陣列:

Array arr = Array.CreateInstance(typeof(int), new[] {5}, new[] {1}); // 索引 1~5
Console.WriteLine(arr.GetLowerBound(0)); // 1
Console.WriteLine(arr.GetUpperBound(0)); // 5

非零基陣列型別為 System.Int32[*](含星號),而非 System.Int32[]。每次存取皆需檢查上下界,JIT 無法優化,效能顯著低於零基陣列。

三、多維陣列 vs 交錯陣列

特性多維陣列 int[,]交錯陣列 int[][]
記憶體分佈單一連續區塊陣列的陣列,多個獨立區塊
建立/銷毀成本一次配置,較低需配置 N+1 個陣列物件,GC 壓力大
存取檢查每次檢查兩個索引,無特殊優化若內層為零基陣列,單層檢查即可
適用場景一次建立、一次遍歷(如矩陣運算)一次建立、多次隨機存取(如稀疏矩陣)

四、效能優化實戰:不安全程式碼與 Stackalloc

1. 固定陣列指標 (fixed) 繞過邊界檢查

unsafe static void Main()
{
    int[,] matrix = new int[3, 3];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            matrix[i, j] = i * 3 + j;

    fixed (int* p = &matrix[0, 0])
    {
        for (int i = 0; i < 3; i++)
        {
            int baseOffset = i * 3;
            for (int j = 0; j < 3; j++)
                Console.WriteLine(p[baseOffset + j]); // 直接指標運算
        }
    }
}

fixed 關鍵字鎖定陣列在 Managed Heap 上的位置,防止 GC 移動記憶體導致指標失效。

2. Stackalloc 直接在 Stack 上配置陣列

unsafe static void Main()
{
    int* arr = stackalloc int[10]; // 無 GC、無物件頭、極快
    for (int i = 0; i < 10; i++) arr[i] = i;
    for (int i = 0; i < 10; i++) Console.WriteLine(arr[i]);
}

適用於極小、生命週期極短、效能敏感的情境(如高頻數學運算),但需謹慎使用以免 Stack Overflow。

五、總結與建議

  • 優先使用零基一維陣列,獲得最佳 JIT 優化。
  • 避免非零基陣列與多維陣列,除非與 legacy API 互操作。
  • 高頻隨機存取場景考慮交錯陣列(內層為零基)。
  • 只有在分析證實為瓶頸時,才引入 unsafe / stackalloc,並嚴格限制範圍、加註釋。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved