練習 - 探索資料類型的強制型轉和轉換

已完成

有多種技術可執行資料類型轉換。 您所選技術取決於您對兩個重要問題的回答:

  • 根據值,嘗試變更值的資料類型會在執行階段擲回例外狀況嗎?
  • 根據值,嘗試變更值的資料類型可能會導致資訊遺失嗎?

在此練習中,您會逐步了解這些問題、其答案的含意,以及當您需要變更資料類型時應該使用的技術。

準備您的撰寫程式碼環境

本課程模組包含實際操作活動,可引導您完成建置及執行示範程式碼的程序。 鼓勵您使用 Visual Studio Code 做為開發環境來完成這些活動。 針對這些活動使用 Visual Studio Code,可協助您更熟悉在全球專業人員使用的開發人員環境中撰寫及執行程式碼。

注意

如果您已完成此 C# 系列中的其他 Microsoft Learn 課程模組,您可能已建立程式碼範例的專案資料夾。 如果是這種情況,您可以略過下列步驟的部分,並刪除用於上一個練習的 Project.cs 檔案中的程式碼。

  1. 打開 Visual Studio Code。

    您可以使用 Windows [開始] 功能表 (或另一個作業系統的對等資源) 來開啟 Visual Studio Code。

  2. 在 Visual Studio Code 的 [檔案] 功能表上,選取 [開啟資料夾]。

  3. 在 [開啟資料夾] 對話方塊中,瀏覽至 Windows Desktop 資料夾。

    如果您在不同的資料夾位置中保留程式碼專案,您可以改用該資料夾位置。 針對本訓練,請務必使用容易找到並記住的位置。

  4. 在 [開啟資料夾] 對話方塊中,選取 [選取資料夾]。

    如果您看到詢問您是否信任作者的安全性對話方塊,請選取 [是]。

  5. 在 Visual Studio Code 的 [終端] 功能表上,選取 [新增終端]。

    請注意,終端面板中的命令提示字元會顯示目前資料夾的資料夾路徑。 例如:

    C:\Users\someuser\Desktop>
    
  6. 若要在指定的資料夾建立新的主控台應用程式,請在終端的命令提示字元中輸入 dotnet new console -o ./CsharpProjects/TestProject 並按下 Enter 鍵。

    這個 .NET CLI 命令會使用 .NET 程式範本,在指定的資料夾位置中建立新的 C# 主控台應用程式專案。 這個命令會為您建立 CsharpProjects 和 TestProject 資料夾,並使用 TestProject 做為 .csproj 檔案的名稱。

  7. 在 [總管] 面板中,展開 CsharpProjects 資料夾。

    您應該會看到 TestProject 資料夾和兩個檔案:名為 Program.cs 的 C# 應用程式檔案,以及名為 TestProject.csproj 的 C# 專案檔。

  8. 在 [總管] 面板中,若要在 [編輯器] 面板中檢視程式碼檔案,請選取 [Program.cs]。

  9. 刪除現有的程式碼。

    您會使用此 C# 主控台專案,在此課程模組期間建立、建置及執行程式碼範例。

  10. 關閉 [終端] 面板。

問題: 嘗試變更值的資料類型會在執行階段擲回例外狀況嗎?

C# 編譯器會嘗試配合您的程式碼,但不會編譯可能導致例外狀況的作業。 若您了解 C# 編譯器的主要考量,會更容易了解其以特定方式運作的原因。

撰寫程式碼,以嘗試新增 intstring,並儲存 int 中的結果

  1. 請確定您已開啟 Visual Studio Code,並在 [編輯器] 面板中顯示 Program.cs。

    注意

    Program.cs 應該是空的。 如果不是,請選取並刪除所有程式碼。

  2. 在 Visual Studio Code 編輯器中輸入下列程式碼:

    int first = 2;
    string second = "4";
    int result = first + second;
    Console.WriteLine(result);
    

    在這裡,您會嘗試將值 24 相加。 值 4string 類型。 這樣行得通嗎?

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

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

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

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

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

    您應該會看見下列的近似輸出

    C:\Users\someuser\Desktop\csharpprojects\TestProject\Program.cs(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'
    

    注意

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

  6. 請花一分鐘時間考慮編譯器為何無法執行第一個程式碼範例。

    錯誤訊息 (3,14): error CS0029: Cannot implicitly convert type 'string' to 'int' 的重要部分會告訴您問題在於 string 資料類型的使用。

    但是,為什麼 C# 編譯器無法直接處理該錯誤呢? 畢竟,您可以採 相反 做法,將數字串連到 string 並以字串變數儲存。 在這裡,您會將 result 變數的資料類型,從 int 變更為 string

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

    int first = 2;
    string second = "4";
    string result = first + second;
    Console.WriteLine(result);
    
  8. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應會觀察到下列輸出:

    24
    

    輸出在數學上不正確,但藉由將值結合為字元 「2」 和 「4」 來完成。

  9. 再次檢查第一個程式碼範例,其中 result 變數為類型 int。 含有錯誤訊息的程式碼。

    int first = 2;
    string second = "4";
    int result = first + second;
    Console.WriteLine(result);
    

    為什麼 C# 編譯器無法判定您想要將包含 4 的變數 second 視為數字,而不是 string?

編譯器會進行安全轉換

C# 編譯器會發現產生中的潛在問題。 變數 second 的類型為 string,因此可能會設定為不同的值,例如 "hello"。 如果 C# 編譯器已嘗試將 "hello" 轉換成會在執行階段造成例外狀況的數字。 為了避免這種情況,C# 編譯器不會以隱含方式執行從 stringint 的轉換。

從 C# 編譯器的觀點來看,更安全的作業是將 int 轉換成 string,並改為執行串連。

若您要使用 string 執行加法,C# 編譯器會要求您更明確控制資料轉換的處理序。 換句話說,它會強制您更進一步參與其中,讓您可以採取適當的預防措施,來處理轉換可能會擲回例外狀況的可能性。

如果您需要將原始資料類型的值變更為新資料類型,且變更可能會在執行階段產生例外狀況,則您必須執行資料轉換

若要執行資料轉換,您可以使用下列其中一種技術:

  • 對資料類型使用協助程式方法
  • 對變數使用協助程式方法
  • 使用 Convert 類別方法

您會在本單元稍後看到將這些技巧用於資料轉換的幾個範例。

問題: 嘗試變更值的資料類型可能會導致資訊遺失嗎?

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    int myInt = 3;
    Console.WriteLine($"int: {myInt}");
    
    decimal myDecimal = myInt;
    Console.WriteLine($"decimal: {myDecimal}");
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    int: 3
    decimal: 3
    

    這個範例的關鍵在於這行程式碼:

    decimal myDecimal = myInt;
    

    因為任何 int 值可以輕鬆放入 decimal 的內部,所以編譯器會執行轉換。

    放大轉換一詞表示您嘗試將值可能包含較少資訊的資料類型,轉換可能保存較多資訊的資料類型。 在此情況下,儲存在類型 int 之變數中的值在轉換成類型 decimal 之變數後,不會遺失資訊。

    當您知道將會執行放大轉換時,您可以運用 隱含轉換。 編譯器會處理隱含轉換。

執行強制型轉

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    decimal myDecimal = 3.14m;
    Console.WriteLine($"decimal: {myDecimal}");
    
    int myInt = (int)myDecimal;
    Console.WriteLine($"int: {myInt}");
    

    若要執行強制型轉,請使用強制型轉運算子 () 來括住資料類型,然後將它放在您要轉換的變數旁邊 (範例: (int)myDecimal)。 您可以對定義的強制型轉資料類型 (int) 執行 明確轉換

  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    decimal: 3.14
    int: 3
    

    這個範例的關鍵在於這行程式碼:

    int myInt = (int)myDecimal;
    

    變數 myDecimal 會保留小數點之後具有有效位數的值。 新增強制型轉指令 (int),會告訴 C# 編譯器您了解這可能會遺失該有效位數,而在此情況下並無大礙。 您會告訴編譯器您正在執行刻意轉換,即 明確轉換

判斷您的轉換是「放大轉換」還是「縮小轉換」

縮小轉換 一詞表示您嘗試將值從可能保存 較多 資訊的資料類型,轉換成可能保存較少資訊的資料類型。 在此情況下,可能會遺失有效位數 (也就是小數點之後的值數目) 之類的資訊。 範例是轉換以類型 decimal 之變數儲存的值為類型 int的變數。 如果您列印出這兩個值,您可能會注意到有資訊遺失。

當您知道將會執行縮小轉換時,您必須執行 強制型轉。 強制型轉是 C# 編譯器的指令,您知道可能會遺失精確度,但您願意接受這種情況。

如果您不確定是否遺失轉換中的資料,請撰寫程式碼以兩種不同的方式執行轉換,並觀察變更。 開發人員經常撰寫小型測試,以進一步瞭解行為,如下一個範例所示。

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    decimal myDecimal = 1.23456789m;
    float myFloat = (float)myDecimal;
    
    Console.WriteLine($"Decimal: {myDecimal}");
    Console.WriteLine($"Float  : {myFloat}");
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    Decimal: 1.23456789
    Float:   1.234568
    

    您可以從輸出中觀察到,將 decimal 強制型轉成 float 是縮小轉換 (因為會失去精確度)。

執行資料轉換

稍早,它指出值從某個資料類型變更到另一個資料類型可能會導致執行時間例外狀況,您應該執行資料轉換。 針對資料轉換,您可以使用三種技術:

  • 對變數使用協助程式方法
  • 對資料類型使用協助程式方法
  • 使用 Convert 類別方法

使用 ToString() 將數位轉換成 string

每個資料類型變數都有 ToString() 方法。 ToString() 方法的作用取決於其如何在所指定類型上執行。 不過,在大部分的基本類型中,都會執行放大轉換。 雖然這不是絕對必要的 (因為您可以在大部分情況下依賴隱含轉換),但它可以向其他開發人員傳達您了解正在進行的刻意作業。

以下是使用 ToString() 方法將 int 值明確轉換成 string 的快速範例。

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    int first = 5;
    int second = 7;
    string message = first.ToString() + second.ToString();
    Console.WriteLine(message);
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。 當您執行程式碼時,輸出應該會顯示兩個值的串連:

    57
    

使用 Parse() 協助程式方法將 string 轉換為 int

大部分的數值資料類型都有 Parse() 方法,它會將字串轉換成指定的資料類型。 在此情況下,您會使用 Parse() 方法,將兩個字串轉換成 int 值,然後將其相加。

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    string first = "5";
    string second = "7";
    int sum = int.Parse(first) + int.Parse(second);
    Console.WriteLine(sum);
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。 當您執行程式碼時,輸出應該會顯示兩個值的總和:

    12
    
  3. 請花一點時間嘗試找出先前程式碼範例的潛在問題? 如果 firstsecond 其中一個變數設定為無法轉換成 int 的值,該怎麼辦? 執行階段會擲回例外狀況。 C# 編譯器和執行階段預期您事先規劃,並防止「不合法的」轉換。 您可以透過數種方式減輕執行時間例外狀況。

    緩解這種情況最簡單的方式是透過使用 TryParse(),這是 Parse() 方法的更好版本。

使用 Convert 類別將 string 轉換為 int

Convert 類別有許多協助程式方法,可將某個類型的值轉換成另一個型別。 在下列程式碼範例中,您會將幾個字串轉換成類型 int 的值。

注意

本練習中的程式碼範例是根據 en-US 文化特性設定所設計,並使用句號 (.) 作為小數分隔符號。 使用採用不同小數分隔符號 (例如逗號 ,) 的文化特性設定來建置和執行程式碼,可能會產生非預期的結果或錯誤。 若要修正此問題,請將程式碼範例中的句點小數分隔符號取代為本機小數分隔符號 (例如 ,)。 另外,若要使用 en-US 文化特性設定來執行程式,請將下列程式碼新增至程式 using System.Globalization; 頂端,並在任何其他 using 陳述式之後新增 CultureInfo.CurrentCulture = new CultureInfo("en-US");

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    string value1 = "5";
    string value2 = "7";
    int result = Convert.ToInt32(value1) * Convert.ToInt32(value2);
    Console.WriteLine(result);
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    35
    

    注意

    為什麼方法名稱為 ToInt32()? 為什麼不是 ToInt()System.Int32 是 .NET 類別庫中的基礎資料類型名稱,C# 程式設計語言會將它對應到關鍵字 int。 因為 Convert 類別也是 .NET 類別庫的一部分,所以會稱呼其完整名稱 (而非其 C# 名稱)。 透過將資料類型定義為 .NET 類別庫的一部分,多種 .NET 語言 (例如 Visual Basic、F#、IronPython 等) 都可以共用相同的資料類型,以及 .NET 類別庫中的相同類別。

    ToInt32() 方法有 19 個多載版本,因此幾乎能接受所有資料類型。

    您在這裡使用了 Convert.ToInt32() 方法與字串,但可能情況下您應該使用 TryParse()

    那麼,您應該使用 Convert 類別嗎? Convert 類別最適合用來將小數位數字轉換成整數 (int),因為它會以您預期的方式無條件進位。

比較強制型轉,並將 decimal 轉換成 int

下列範例示範當您嘗試將 decimal 強制型轉成 int (縮小轉換),以及使用 Convert.ToInt32() 方法將相同的 decimal 轉換成 int 時,會發生什麼狀況。

  1. 刪除或使用行註解運算子 //,將上一個練習步驟中的程式碼註解化,並新增下列程式碼:

    int value = (int)1.5m; // casting truncates
    Console.WriteLine(value);
    
    int value2 = Convert.ToInt32(1.5m); // converting rounds up
    Console.WriteLine(value2);
    
  2. 儲存您的程式碼檔案,然後使用 Visual Studio Code 來執行程式碼。

    您應該會看見下列輸出:

    1
    2
    

轉換截斷和轉換四捨五入

當您強制型轉 int value = (int)1.5m; 時,浮動值會被截斷,結果為 1,這表示會完全忽略小數點之後的值。 您可以將常值浮動變更為 1.999m,而強制型轉的結果會相同。

當您使用 Convert.ToInt32() 進行轉換時,常值浮動值會適當地無條件進位到 2。 如果您將常值變更為 1.499m,則會無條件進位到 1

概括回顧

您涵蓋了資料轉換與強制型轉的數個重要概念:

  • 在執行資料轉換時防止執行階段錯誤
  • 執行明確轉換以告知編譯器您了解遺失資料的風險
  • 在執行放大轉換時,依賴編譯器來執行隱含強制型轉
  • 使用 () 轉換運算子與資料類型執行強制型轉 (例如 (int)myDecimal)
  • 當您想要執行縮小轉換,但想要執行四捨五入,而不是截斷資訊時,請使用 Convert 類別

檢定您的知識

1.

將十進位類型轉換成 C# 中 int 類型的最佳技術是哪一種?

2.

下列哪一個轉換會將值四捨五入 (與截斷)?