using System;
using System.Runtime.Serialization;
[Serializable]
public class TooManyItemsException : Exception
{
public int MaxItems { get; }
public int AttemptedItems { get; }
public TooManyItemsException()
: base("項目數量超過限制") { }
public TooManyItemsException(string message)
: base(message) { }
public TooManyItemsException(string message, Exception inner)
: base(message, inner) { }
// 完整建構函式:支援序列化
protected TooManyItemsException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
MaxItems = info.GetInt32(nameof(MaxItems));
AttemptedItems = info.GetInt32(nameof(AttemptedItems));
}
// 便利建構函式
public TooManyItemsException(int max, int attempted)
: base($"嘗試存取 {attempted} 項,上限 {max} 項")
{
MaxItems = max;
AttemptedItems = attempted;
}
// 序列化支援
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue(nameof(MaxItems), MaxItems);
info.AddValue(nameof(AttemptedItems), AttemptedItems);
}
}
public class ExceptionTester
{
public static void Main()
{
var tester = new ExceptionTester();
try
{
tester.GenerateException(5);
}
catch (TooManyItemsException ex)
{
Console.WriteLine($"自訂例外:{ex.Message}");
Console.WriteLine($"上限:{ex.MaxItems},嘗試:{ex.AttemptedItems}");
}
catch (Exception ex)
{
Console.WriteLine($"其他例外:{ex.Message}");
}
finally
{
Console.WriteLine("Finally from Main.");
}
}
void GenerateException(int iterations)
{
int maxSize = 3;
byte[] buffer = new byte[maxSize];
using (var sw = new StreamWriter("log.txt"))
{
try
{
if (iterations > buffer.Length)
throw new TooManyItemsException(maxSize, iterations); // 拋出自訂例外
for (byte i = 0; i < iterations; i++)
{
sw.WriteLine($"Byte {i+1}: {i}");
buffer[i] = i;
}
}
finally
{
Console.WriteLine("Finally from GenerateException.");
sw.WriteLine("Close");
}
}
}
}
try
{
// 可能拋出多種例外
}
catch (TooManyItemsException ex) // 最具體的優先
{
// 處理自訂例外
}
catch (ArgumentNullException ex) // 具體系統例外
{
// 處理空參數
}
catch (IOException ex) // 另一具體例外
{
// 處理 IO
}
catch (Exception ex) // 最基底,最後捕獲
{
// 記錄未預期錯誤
}
Environment.FailFast、進程被殺死、無限迴圈、堆疊溢位try
{
RiskyOperation();
}
catch (Exception ex) when (ex.Message.Contains("timeout")) // C# 6+
{
// 僅捕獲包含 "timeout" 的例外
HandleTimeout();
}
catch (Exception ex) when (ShouldRetry(ex)) // 可呼叫方法
{
RetryOperation();
}
catch (Exception ex)
{
// 其他例外
}
// 等同 try/finally 呼叫 Dispose()
using (var sw = new StreamWriter("file.txt"))
{
sw.WriteLine("資料");
} // 編譯器自動產生 finally { sw.Dispose(); }
// C# 8+ using 宣告 (無大括號)
using var sw = new StreamWriter("file.txt");
sw.WriteLine("資料");
// 方法結束自動 Dispose
❌ 不好:用例外控制正常流程
try { return dict[key]; }
catch (KeyNotFoundException) { return default; }
✅ 好:用 TryGetValue / ContainsKey
if (dict.TryGetValue(key, out var value)) return value;
return default;
| 應用類型 | 處理事件 |
|---|---|
| WinForms | Application.ThreadException + AppDomain.CurrentDomain.UnhandledException |
| WPF | DispatcherUnhandledException + AppDomain.CurrentDomain.UnhandledException |
| ASP.NET Core | UseExceptionHandler / UseDeveloperExceptionPage 中介軟體 |
| Console | AppDomain.CurrentDomain.UnhandledException + TaskScheduler.UnobservedTaskException |
Message、InnerException、自訂屬性Exception 而非 ApplicationException (已棄用建議)[Serializable] 支援跨應用程式域/遠端GetObjectDatafinally 中拋出新例外 (會遮蔽原始例外)