深入淺出 C# 4/e 第12章 例外處理 心得分享


分類

建立時間: 2022年12月31日 01:13
更新時間: 2023年9月14日 08:42

心得

此心得包含第12章,Unity 實驗室 #6 場景導航,例外處理在許多程式中相當常見,不只是 C# 才有,這次我會分享一些不錯的例外處理程式技巧,如果完全不知道什麼是例外處理的朋友們,建議大家先自行學習後再來看本篇內容比較合適。

Unity 實驗室 #6 場景導航心得

這篇是 Unity NavMesh 強大的導航功能 的後續,裡面加了更多的障礙,還包含一個會移動的障礙物,但這次我就不再教學了,有興趣得可以購買此書閱讀,值得分享的是書中提到了控制攝影機的腳本,我另外寫一篇 Unity 用鍵盤上下左右實現攝影機移動 分享給大家。

一個程式的重點大集合

以下程式包含下列幾點重點

  • 一定要執行的程式,使用 finally 區塊
  • 需要用到 Exception 物件才指定變數名稱,如 catch (UnauthorizedAccessException exception)
  • 盡量捕捉更清楚的例外,而不是通用的例外

Program.cs

var firstLine = "No first line was read";

try
{
    var lines = File.ReadAllLines(args[0]);

    firstLine = (lines.Length > 0) ? lines[0] : "The file was empty";
}
catch (IndexOutOfRangeException)
{
    Console.Error.WriteLine("Please specify a filename.");
}
catch (FileNotFoundException)
{
    Console.Error.WriteLine("Unable to find file: {0}", args[0]);
}
catch (UnauthorizedAccessException exception)
{
    Console.Error.WriteLine(
        "File {0} could not be accessed: {1}",
        args[0],
        exception.Message);
}
finally
{
    Console.WriteLine(firstLine);
}

catch-all exception

雖然要盡量避免用一個 catch 捕捉所有的例外,但有時候不是很重要的程式,還是可以偷懶用一下

下面是通用 catch 方便的寫法

Program.cs

var firstLine = "No first line was read";

try
{
    var lines = File.ReadAllLines(args[0]);

    firstLine = (lines.Length > 0) ? lines[0] : "The file was empty";
}
catch
{
    Console.Error.WriteLine("Oops!");
}
finally
{
    Console.WriteLine(firstLine);
}

將捕捉的例外往上浮

我有時候也會這麼做,有錯就要認,這是我內心的想法,雖然我對我寫的程式有信心,或者這段程式曾發生過哪個例外,但我已經修正了,保險起見我還是寫個例外捕捉,假設我真的捕捉到了,我做了某些事情,然後再讓例外跑出。

example.cs

try
{
    // 可能丟出例外的程式
}
catch (DivideByZeroException exception)
{
    Console.Error.WriteLine($"Got an error: {exception.Message}");
    throw;
}

拋出例外

自己寫的檢查程式不通過時,可以自己拋出例外,讓你更容易找到臭蟲。

下面是參數 amount 必須大於0,否則就會拋出參數例外。

example.cs

public void ReceiveCash(int amount)
{
    if(amount <= 0)
    {
        throw new ArgumentException($"Must receive a positive value", "amount");
    }
    Cash += amount;
}

自訂例外

自訂例外很簡單!但久了沒用很容易忘記,忘記時再回來看一下這裡。
這個範例是繼承 Exception,當然也可以繼承 Exception 的子類別。

OutOfCashException.cs

/// <summary>
/// 現金不足例外
/// </summary>
public class OutOfCashException : Exception
{
    public OutOfCashException(string message) : base(message)
    {
    }
}

之後就可以像這樣拋出例外 throw new OutOfCashException("錯誤訊息");

例外過濾器

使用 when 關鍵字來要求例外處理常式只在特定條件下捕捉例外。
以下為 Microsoft 範例

Program.cs

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Console.WriteLine(MakeRequest().Result);
    }

    public static async Task<string> MakeRequest()
    {
        var client = new HttpClient();
        var streamTask = client.GetStringAsync("https://localHost:10000");
        try
        {
            var responseText = await streamTask;
            return responseText;
        }
        catch (HttpRequestException e) when (e.Message.Contains("301"))
        {
            return "Site Moved";
        }
        catch (HttpRequestException e) when (e.Message.Contains("404"))
        {
            return "Page Not Found";
        }
        catch (HttpRequestException e)
        {
            return e.Message;
        }
    }
}

參考

觀看次數: 599
c#catchexceptionfinallytrywhen例外
按讚追蹤 Enjoy 軟體 Facebook 粉絲專頁
每週分享資訊技術

一杯咖啡的力量,勝過千言萬語的感謝。

支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!