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

Effective C# 原則 4:用條件屬性取代 #if 預處理器(下)

     編輯:關於C語言

條件屬性實戰:偵錯驗證方法

[Conditional("DEBUG")]
private void CheckState()
{
    string caller = new StackTrace().GetFrame(1).GetMethod().Name;
    Trace.WriteLine($"Entering CheckState for Person (called by {caller})");

    Debug.Assert(_lastName != null, caller, "Last Name cannot be null");
    Debug.Assert(_lastName.Length > 0, caller, "Last Name cannot be blank");
    Debug.Assert(_firstName != null, caller, "First Name cannot be null");
    Debug.Assert(_firstName.Length > 0, caller, "First Name cannot be blank");

    Trace.WriteLine("Exiting CheckState for Person");
}

套用於屬性存取器

public string LastName
{
    get
    {
        CheckState(); // DEBUG 時執行驗證,RELEASE 時直接移除呼叫
        return _lastName;
    }
    set
    {
        CheckState();
        _lastName = value;
        CheckState();
    }
}

條件屬性 vs #if 優勢對比

特性ConditionalAttribute#if / #endif
呼叫端處理編譯器移除呼叫指令,零開銷保留空方法呼叫,仍有呼叫開銷
程式碼結構邏輯集中在方法內,乾淨散落在各處,難以維護
編譯器支援原生識別,IntelliSense 正常預處理器指令,工具支援較弱
副作用風險無(呼叫被移除,引數不評估)高(引數仍會評估,如 GetDiagnostics())
適用範圍僅方法任意程式碼區塊

#if 經典 Bug:引數副作用

public void BadExample()
{
    string msg = null;
#if DEBUG
    msg = GetDiagnostics(); // 只有 DEBUG 時賦值
#endif
    Console.WriteLine(msg); // RELEASE 印出 null → 空行,非預期!
}

條件屬性版本:

[Conditional("DEBUG")]
private void LogDiagnostics(string msg) { Console.WriteLine(msg); }

public void GoodExample()
{
    LogDiagnostics(GetDiagnostics()); // RELEASE 時整個呼叫(含引數評估)被移除
}

使用限制與注意

  • 只能套用在 void 回傳的方法
  • 不能用於介面方法、覆寫方法、委派目標
  • 標記為 Conditional 的方法不可為 public(建議 private/internal)
  • 多重條件:[Conditional("DEBUG"), Conditional("TRACE")] 任一符合即保留

最佳實務

  1. 偵錯斷言、追蹤、日誌、效能計數器 → 用 Conditional("DEBUG")
  2. 編譯時常數切換(如功能旗標)→ 用 #if FEATURE_X
  3. 平台相關程式碼 → 用 #if NETCOREAPP / #if WINDOWS
  4. 永遠不要在 #if 區塊內放置有副作用的運算式
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved