プリプロセッサ ディレクティブ

# 条件式

以下をコンパイルすると、定義されているディレクティブに応じて異なる値が返されます。

// Compile with /d:A or /d:B to see the difference
string SomeFunction() 
{
#if A
    return "A";
#elif B
    return "B";
#else
    return "C";
#endif
}

条件式は通常、デバッグ ビルドの追加情報をログに記録するために使用されます。

void SomeFunc()
{
    try
    {
        SomeRiskyMethod();
    }
    catch (ArgumentException ex)
    {
        #if DEBUG
        log.Error("SomeFunc", ex);
        #endif

        HandleException(ex);
    }
}

# その他のコンパイラ命令

# 行

#line 警告とエラーを出力するときにコンパイラによって報告される行番号とファイル名を制御します。

void Test()
{
    #line 42 "Answer"
    #line filename "SomeFile.cs"
    int life; // compiler warning CS0168 in "SomeFile.cs" at Line 42
    #line default
    // compiler warnings reset to default
}

# プラグマ チェックサム

#pragma checksum デバッグ用に、生成されたプログラム データベース (PDB) の特定のチェックサムを指定できます。

#pragma checksum "MyCode.cs" "{00000000-0000-0000-0000-000000000000}" "{0123456789A}"

# シンボルの定義と未定義

コンパイラ シンボルは、コードの特定のセクションを条件付きで実行するためにチェックできる、コンパイル時に定義されるキーワードです。

コンパイラ シンボルを定義するには、3 つの方法があります。コードで定義できます:

#define MYSYMBOL

これらは、Visual Studio の [プロジェクト プロパティ]> [ビルド]> [条件付きコンパイル シンボル] で定義できます:

(DEBUG に注意してください そして TRACE 独自のチェックボックスがあり、明示的に指定する必要はありません。)

または、コンパイル時に /define:[name] を使用して定義することもできます C# コンパイラ、csc.exe をオンにします .

#undefine を使用してシンボルを未定義にすることもできます

これの最も一般的な例は DEBUG です これは、アプリケーションが (リリース モードではなく) デバッグ モードでコンパイルされたときに、Visual Studio によって定義されます。

public void DoBusinessLogic()
{
    try
    {
        AuthenticateUser();
        LoadAccount();
        ProcessAccount();
        FinalizeTransaction();
    }
    catch (Exception ex)
    {
#if DEBUG
        System.Diagnostics.Trace.WriteLine("Unhandled exception!");
        System.Diagnostics.Trace.WriteLine(ex);
        throw;
#else
        LoggingFramework.LogError(ex);
        DisplayFriendlyErrorMessage();
#endif
    }
}

上記の例では、アプリケーションのビジネス ロジックでエラーが発生した場合、アプリケーションがデバッグ モードでコンパイルされている場合 (および DEBUG シンボルが設定されている場合)、エラーがトレース ログに書き込まれ、デバッグのために例外が再スローされます。ただし、アプリケーションがリリース モードでコンパイルされている場合 (および DEBUG がない場合) シンボルが設定されている場合)、ロギング フレームワークを使用してエラーを静かにログに記録し、わかりやすいエラー メッセージをエンド ユーザーに表示します。

# 地域ブロック

#region を使用 と #endregion 折りたたみ可能なコード領域を定義します。

#region Event Handlers

public void Button_Click(object s, EventArgs e)
{
    // ...
}

public void DropDown_SelectedIndexChanged(object s, EventArgs e)
{
    // ...
}

#endregion

これらのディレクティブは、折りたたみ可能な領域 (Visual Studio など) をサポートする IDE を使用してコードを編集する場合にのみ役立ちます。

# コンパイラ警告の無効化と復元

#pragma warning disable を使用してコンパイラの警告を無効にすることができます #pragma warning restore を使用して復元します :

#pragma warning disable CS0168

// Will not generate the "unused variable" compiler warning since it was disabled
var x = 5;

#pragma warning restore CS0168

// Will generate a compiler warning since the warning was just restored
var y = 8;

コンマ区切りの警告番号を使用できます:

#pragma warning disable CS0168, CS0219

CS プレフィックスはオプションであり、混在させることもできます (ただし、これはベスト プラクティスではありません):

#pragma warning disable 0168, 0219, CS0414

# コンパイラの警告とエラーの生成

コンパイラ警告は #warning を使用して生成できます ディレクティブ、およびエラーは同様に #error を使用して生成できます

#if SOME_SYMBOL
#error This is a compiler Error.
#elif SOME_OTHER_SYMBOL
#warning This is a compiler Warning.
#endif

# Conditional 属性の使用

Conditional を追加する System.Diagnostics の属性 名前空間をメソッドに追加することは、ビルドで呼び出されるメソッドと呼び出されないメソッドを明確に制御する方法です。

#define EXAMPLE_A

using System.Diagnostics;
class Program
{
    static void Main()
    {
        ExampleA(); // This method will be called
        ExampleB(); // This method will not be called
    }

    [Conditional("EXAMPLE_A")]
    static void ExampleA() {...}

    [Conditional("EXAMPLE_B")]
    static void ExampleB() {...}
}

# プロジェクト レベルのカスタム プリプロセッサ

テストなどで一部のアクションをスキップする必要がある場合、プロジェクト レベルでカスタムの条件付き前処理を設定すると便利です。

Solution Explorer に移動 -> 右クリック 変数を設定したいプロジェクトで -> Properties -> Build -> 一般的に検索フィールド Conditional compilation symbols ここに条件変数を入力してください

一部のコードをスキップするコード例:

public void Init()
{
    #if !IGNOREREFRESHDB
    // will skip code here
     db.Initialize();
    #endif
}

# 構文

  • #define [シンボル] // コンパイラ シンボルを定義します。
  • #undef [記号] // コンパイラ シンボルの定義を解除します。
  • #warning [警告メッセージ] // コンパイラの警告を生成します。 #if で役立ちます。
  • #error [エラー メッセージ] // コンパイラ エラーを生成します。 #if で役立ちます。
  • #line [行番号] (ファイル名) // コンパイラの行番号 (およびオプションでソース ファイル名) をオーバーライドします。 T4 テキスト テンプレートで使用します。
  • #pragma warning [disable|restore] [警告番号] // コンパイラの警告を無効化/復元します。
  • #pragma checksum "[ファイル名] " "[ガイド] " "[チェックサム] " // ソース ファイルの内容を検証します。
  • #region [地域名] // 折りたたみ可能なコード領域を定義します。
  • #endregion // コード領域ブロックを終了します。
  • #if [条件] // 条件が true の場合、以下のコードを実行します。
  • #else // #if の後に使用
  • #elif [状態] // #if の後に使用
  • #endif // #if で始まる条件付きブロックを終了します。

# コメント

プリプロセッサ ディレクティブは通常、ソース プログラムを変更しやすくし、さまざまな実行環境でコンパイルしやすくするために使用されます。ソース ファイル内のディレクティブは、特定のアクションを実行するようにプリプロセッサに指示します。たとえば、プリプロセッサは、テキスト内のトークンを置き換えたり、他のファイルの内容をソース ファイルに挿入したり、テキストのセクションを削除してファイルの一部のコンパイルを抑制したりできます。プリプロセッサ行は、マクロ展開の前に認識され、実行されます。したがって、マクロがプリプロセッサ コマンドのように見えるものに展開された場合、そのコマンドはプリプロセッサによって認識されません。

プリプロセッサ ステートメントは、ソース ファイル ステートメントと同じ文字セットを使用しますが、エスケープ シーケンスはサポートされていません。プリプロセッサ ステートメントで使用される文字セットは、実行文字セットと同じです。プリプロセッサは負の文字値も認識します。

# 条件式

条件式 (#if#elif など) ブール演算子の限定されたサブセットをサポートします。それらは:

  • ==!= .これらは、シンボルが true (定義済み) か false (未定義) かをテストするためにのみ使用できます
  • &&||!
  • ()

例:

#if !DEBUG && (SOME_SYMBOL || SOME_OTHER_SYMBOL) && RELEASE == true
Console.WriteLine("OK!");
#endif

「OK!」を出力するコードをコンパイルします。 DEBUG の場合はコンソールに SOME_SYMBOL のいずれかで定義されていません または SOME_OTHER_SYMBOL が定義され、RELEASE が定義されています。

注:これらの置換はコンパイル時に行われます したがって、実行時に検査することはできません。 #if を使用してコードを削除 コンパイラの出力の一部ではありません。

関連項目:MSDN の C# プリプロセッサ ディレクティブを参照してください。