練習 - 探索 Clear() 與 Resize()

已完成

當您持續為物流公司建置棧板追蹤程式時,假設您也需要追蹤新棧板,並移除舊棧板而不再予以追蹤。 如何完成建立新增和移除棧板的追蹤功能?

使用陣列方法來清除陣列和調整大小

Array.Clear() 方法可讓您移除陣列中特定元素的內容,並將其取代為陣列預設值。 例如,在 string 陣列中,清除的元素值會取代為 null,當您清除 int 陣列元素時,即會使用 0 (零) 來完成取代。

Array.Resize() 方法會新增或移除陣列中的元素。

  1. 刪除或使用行註解運算子 //,將上一個練習中的所有程式碼標記為註解。

  2. 在 Visual Studio Code 編輯器更新您的程式碼,如下所示:

    string[] pallets = { "B14", "A11", "B12", "A13" };
    Console.WriteLine("");
    
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"Clearing 2 ... count: {pallets.Length}");
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    
  3. 請花一分鐘的時間專注於程式碼 Array.Clear(pallets, 0, 2);

    在這裡,您使用 Array.Clear() 方法來清除儲存在 pallets 陣列元素中的值,從索引 0 開始並清除 2 元素。

  4. 在 Visual Studio Code 的 [檔案] 功能表上,選取 [儲存]。

    在建置或執行程式碼之前,必須先儲存 Program.cs 檔案。

  5. 在 [總管] 面板中,若要在 TestProject 資料夾位置開啟 [終端],請以滑鼠右鍵按一下 [TestProject],然後選取 [在整合式終端機中開啟]。

    終端窗格應開啟,且應包含命令提示字元,顯示已對 TestProject 資料夾位置開啟終端。

  6. 在終端命令提示字元中,若要執行程式碼,請輸入 dotnet run,然後按 Enter 鍵。

    注意

    如果您看到訊息指出「找不到要執行的專案」,請確定終端命令提示字元會顯示預期的 TestProject 資料夾位置。 例如:C:\Users\someuser\Desktop\csharpprojects\TestProject>

    當您執行程式碼時,您將會看到儲存在陣列前兩個元素中的值已被清除。在 Length 屬性與 foreach 陳述式中,這些元素仍然存在,但它們現在是空的。

    Clearing 2 ... count: 4
    -- 
    -- 
    -- B12
    -- A13
    
    

空字串與 Null 的比較

當您使用 Array.Clear() 時,已清除的元素再也不會參考記憶體中的字串。 事實上,該元素根本不會指向任何東西。 不會指向任何東西是一個重要的概念,但是一開始可能很難掌握。

若您嘗試擷取受 Array.Clear() 方法影響的元素值,可以嗎?

存取已清除元素的值

需要兩種方法來判斷已清除元素的值,以查看 C# 編譯器如何與 Null 值搭配運作。

  1. Array.Clear(pallets, 0, 2); 程式碼周圍插入新的程式碼,如下所示:

    Console.WriteLine($"Before: {pallets[0]}");
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"After: {pallets[0]}");
    
    
  2. 驗證您的程式碼應符合下列程式碼清單:

    string[] pallets = { "B14", "A11", "B12", "A13" };
    Console.WriteLine("");
    
    Console.WriteLine($"Before: {pallets[0]}");
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"After: {pallets[0]}");
    
    Console.WriteLine($"Clearing 2 ... count: {pallets.Length}");
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    
  3. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    Before: B14
    After:
    Clearing 2 ... count: 4
    --
    --
    -- B12
    -- A13
    
    

若您將焦點放在 After: 輸出行,您可能會認為儲存在 pallets[0] 中的值是空字串。 不過,C# 編譯器會隱含地將 Null 值轉換為空字串來顯示。

在已清除的元素上呼叫字串協助程式方法

為了證明儲存在 pallets[0] 中的值在清除後是 Null,您會修改程式碼範例來呼叫 pallets[0] 上的 ToLower() 方法。 若它是字串,應該就會正常運作。 但若它是 Null,應該會導致程式碼擲回例外狀況。

  1. 若要在每次嘗試寫入 ToLower() 主控台時呼叫 pallets[0] 方法,請按以下方式更新程式碼:

    Console.WriteLine($"Before: {pallets[0].ToLower()}");
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"After: {pallets[0].ToLower()}");
    
  2. 確定程式碼符合下列程式碼清單:

    string[] pallets = { "B14", "A11", "B12", "A13" };
    Console.WriteLine("");
    
    Console.WriteLine($"Before: {pallets[0].ToLower()}");
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"After: {pallets[0].ToLower()}");
    
    Console.WriteLine($"Clearing 2 ... count: {pallets.Length}");
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    
  3. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。 這次,當您執行程式碼時,您將會看到較大的錯誤訊息。 若您剖析文字,您將會看到下列訊息:

    System.NullReferenceException: Object reference not set to an instance of an object.
    
    

    擲回此例外狀況的原因是,C# 編譯器有機會隱含地將 Null 轉換為空字串之前,嘗試對 pallets[0] 元素的內容呼叫該方法。

    這個故事的啟示是,Array.Clear() 將移除陣列元素對值的參考 (若有參考存在)。 若要修正此問題,您可能會在嘗試列印值之前,檢查值是否為 Null。

    若要避免該錯誤,我們可以在存取可能是 Null 的陣列元素之前,新增 if 陳述式。

if (pallets[0] != null)
    Console.WriteLine($"After: {pallets[0].ToLower()}");

調整陣列的大小以新增更多元素

  1. 接著,修改步驟 1 的程式碼清單,以包括用於調整陣列大小的程式碼。 完成時,您的程式碼應該符合下列程式碼清單:

    string[] pallets = { "B14", "A11", "B12", "A13" };
    Console.WriteLine("");
    
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"Clearing 2 ... count: {pallets.Length}");
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    Console.WriteLine("");
    Array.Resize(ref pallets, 6);
    Console.WriteLine($"Resizing 6 ... count: {pallets.Length}");
    
    pallets[4] = "C01";
    pallets[5] = "C02";
    
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    
  2. 花幾分鐘的時間專注在 Array.Resize(ref pallets, 6); 行。

    在這裡,您會呼叫 Resize() 方法,並使用 ref 關鍵字,藉傳址傳入 pallets 陣列。 在某些案例中,方法會要求您以傳值方式 (預設值) 或藉傳址 (使用 ref 關鍵字) 傳遞引數。 之所以需要這樣做,是需要對如何在 .NET 中管理物件進行冗長而複雜的解釋。 可惜的是,這已超出此課程模組的範圍。 如果有疑慮,建議您查看 Intellisense 或 Microsoft Docs,以取得有關如何適當地呼叫指定方法的範例。

    在此案例中,您將 pallets 陣列的元素數目從 4 個調整為 6 個。 新元素會新增到目前元素的結尾。 在您為這兩個新元素指派值之前,它們將是 Null。

  3. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。 當您執行程式碼時,應該會看到下列輸出。

    Clearing 2 ... count: 4
    -- 
    -- 
    -- B12
    -- A13
    
    Resizing 6 ... count: 6
    -- 
    -- 
    -- B12
    -- A13
    -- C01
    -- C02
    
    

調整陣列的大小以移除元素

相反地,您可以使用 Array.Resize() 來移除陣列元素。

  1. 在 Visual Studio Code 編輯器更新您的程式碼,如下所示:

    string[] pallets = { "B14", "A11", "B12", "A13" };
    Console.WriteLine("");
    
    Array.Clear(pallets, 0, 2);
    Console.WriteLine($"Clearing 2 ... count: {pallets.Length}");
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    Console.WriteLine("");
    Array.Resize(ref pallets, 6);
    Console.WriteLine($"Resizing 6 ... count: {pallets.Length}");
    
    pallets[4] = "C01";
    pallets[5] = "C02";
    
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    Console.WriteLine("");
    Array.Resize(ref pallets, 3);
    Console.WriteLine($"Resizing 3 ... count: {pallets.Length}");
    
    foreach (var pallet in pallets)
    {
        Console.WriteLine($"-- {pallet}");
    }
    
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。 當執行程式碼時,應該會看見下列輸出:

    Clearing 2 ... count: 4
    --
    --
    -- B12
    -- A13
    
    Resizing 6 ... count: 6
    --
    --
    -- B12
    -- A13
    -- C01
    -- C02
    
    Resizing 3 ... count: 3
    --
    --
    -- B12
    
    

    請注意,呼叫 Array.Resize() 並不會消除前兩個 Null 元素。 相反地,它會移除最後三個元素。 值得注意的是,即使最後三個元素包含字串值,仍會移除。

您是否可從陣列移除 Null 元素?

Array.Resize() 方法未從陣列移除空元素,是否有其他協助程式方法可自動執行該作業? 否。 從陣列中清空元素的最佳方式是,透過逐一查看每個項目並使變數 (計數器) 遞增,來計算非 Null 元素的數目。 接著,您會建立大小為計數器變數的第二個陣列。 最後,您會對原始陣列中的每個元素執行迴圈,並將非 Null 值複製到新陣列。

概括回顧

以下提供一些您在此單元中討論過的重要概念:

  • 使用 Clear() 方法來清空陣列中的元素值。
  • 使用 Resize() 方法來變更陣列中的元素數目,在陣列結尾移除或新增元素。
  • 新的陣列元素與已清除的元素為 Null,表示它們並未指向記憶體中的值。

檢定您的知識

1.

哪一個最能描述程式碼 Array.Clear(pallets, 0, 2); (其中 palletsstring 陣列)?