0

C# でいくつかの条件付きコンパイルを行う必要がありますが、グローバル シンボルの数を低く抑えるようにも要求されました。したがって、(そして多くのシンボルを追加する)代わりに#if ENABLE_MODULE、私は主に opt-out を行います#if !DISABLE_MODULE

コア ループをプロファイリングするときは、結果をより明確に表示するために、何をオフにするかを細かく制御したいと考えています。ただし、空の assert 呼び出し (#ifメソッド本体内) の場合でも、呼び出しだけでかなりの時間がかかります。そのため、属性を使用して呼び出しを完全に削除し、コードを読みにくくするセクションで[Conditional]すべてを囲む必要がないようにしました。#if

ただし[Conditional]、いくつかの注意事項があります。

  1. 一緒にのみ OR できます。
  2. not ! を使用した否定 内部条件は許可されていません。
  3. それらを AND 結合する方法はありません。
  4. #if とは異なり、実際に呼び出されたメソッドのファイル スコープ シンボル定義ではなく、呼び出し元のファイル スコープ シンボル定義によって解釈されます。

私は回避策を考え出しましたが、見栄えが悪く、コードを繰り返す傾向があります (以下の__Convoluted()方法を参照)。無効化されたセクション内のコード#ifは、Visual Studio のコメントのように扱われるため (名前のリファクタリングがないため)、すべてのシンボルの組み合わせがチェックされないなどの理由で、さらに悪化し、壊れたコミットになります。

いくつかのアンブレラ シンボルを使用することを考えましたが、それではすべてを正の OR で考える必要があり、たとえば、ほとんどのアサートが必要な場合もありますが、一部のモジュールからはアサートされません。

おそらく、これには実用的なものではなく、ソフトウェアアーキテクチャの答えがあります。

Unity を使用しているため、ファイル (csc.rsp) 内のコンパイラ パラメーターを置き換えるビルド スクリプトを実行しないと、構成 (デバッグ/リリース/開発ビルド) ごとにシンボルを細かく制御することはできません。

私の質問:これを処理するより良い方法はありますか?

御時間ありがとうございます。

さまざまな代替案を試して少し宿題をし、いくつかの結論に達しました(次のコード)

最小限のテスト ケース C# .NET コンソール アプリ

ユーティリティファイル

//ENABLE is a global symbol definition at project level

#if ENABLE && EXTRA
    #define _COMBINED
#endif

#if !ENABLE
    #define _DISABLE
#endif

using System;
using System.Diagnostics;

public static class Utility {

    [Conditional("ENABLE")]
    public static void Call(string msg) {
        Console.WriteLine(msg);
    }

    [Conditional("ENABLE"), Conditional("OTHER")]
    public static void CallOr(string msg) {
        Console.WriteLine(msg);
    }

    [Conditional("_DISABLE")]
    public static void CallNot(string msg) {
        Console.WriteLine(msg);
    }

    public static void CallNotInternal(string msg) {
        CallNot(msg);
    }

    [Conditional("_COMBINED")]
    public static void CallAnd(string msg) {
        Console.WriteLine(msg);
    }

    public static void CallAndInternal(string msg) {
        CallAnd(msg);
    }

#if ENABLE //!_DISABLE
    [Conditional("_NEVER")] // <-- Hack to remove MSIL call.
    public static void CallNotConvoluted(string msg) { }
#else
    public static void CallNotConvoluted(string msg) {
        Console.WriteLine(msg);
    }   
#endif


#if !(ENABLE && EXTRA) //!_COMBINED
    [Conditional("_NEVER")] // <-- Hack to remove MSIL call.
    public static void CallAndConvoluted(string msg) { }
#else
    public static void CallAndConvoluted(string msg) {
        Console.WriteLine(msg);
    }   
#endif


}

さまざまな呼び出しの組み合わせ

//Works as expected
Utility.Call("Call1");

//Works as expected
Utility.CallOr("CallOr");

//Doesn't work because _DISABLE is not defined in this file
//(although it is defined at Utility)
Utility.CallNot("CallNot");

//Works because _DISABLE is defined at Utility (where CallNotInternal resides)
//BUT would have extra "empty" call
Utility.CallNotInternal("CallNotInternal");

//Doesn't work because _COMBINED is not defined in this file
//(although it is defined at Utility)
Utility.CallAnd("CallAnd");

//Works because _COMBINED is defined at Utility (where CallAndInternal resides)
//BUT would have extra "empty" call
Utility.CallAndInternal("CallAndInternal");

//Works but it seems kind of hacky/bulky
Utility.CallNotConvoluted("CallNotConvoluted");

//Works but it seems kind of hacky/bulky
Utility.CallAndConvoluted("CallAndConvoluted");

コードは、グローバル シンボルが次のように設定されている場合に出力します。Conditional が #if のように機能しないことCallAndに注意してください。CallNot

ENABLE and EXTRA
----------------
Call1
CallOr
CallAndInternal
CallAndConvoluted



ENABLE
-----
Call1
CallOr



(no symbols)
------------
CallNotInternal
CallNotConvoluted
4

0 に答える 0