デバッグとリリースのC#if / thenディレクティブ


432

ソリューションのプロパティで、唯一のプロジェクトの構成を「リリース」に設定しました。

メインルーチンの最初にこのコードがあり、「Mode = Debug」と表示されています。最上部にも次の2行があります。

#define DEBUG 
#define RELEASE

私は正しい変数をテストしていますか?

#if (DEBUG)
            Console.WriteLine("Mode=Debug"); 
#elif (RELEASE)
            Console.WriteLine("Mode=Release"); 
#endif

私の目標は、デバッグモードとリリースモードに基づいて、変数に異なるデフォルトを設定することです。


13
デバッグとリリースの両方を定義しています。
Eric Dahlvang、2010年

回答:


718

DEBUG/ _DEBUGはVSで既に定義されているはずです。

#define DEBUGコードからを削除します。特定のビルドのビルド構成にプリプロセッサを設定します。

"Mode = Debug"と表示されるのは、が原因でが#defineスキップされるためelifです。

チェックする正しい方法は次のとおりです。

#if DEBUG
    Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif

確認しないでくださいRELEASE


77
RELEASEのみをチェックしたい場合は、次のように追加できます:#if!DEBUG

3
なぜ#ifありませんか#ifdef
Bob Stein

23
@ BobStein-VisiBoneここではC#について話していることを思い出してください。C #ifdefはC / C ++のプリプロセッサに固有のものではなく、C#はの使用を義務付けています#if
jduncanator 2014

27
@ジェス、これはReSharperではなくVisual Studioがグレーアウトを実行していると思う
ダコタハイコック

1
@DakotahHicock正解です。リシャーパーを使用せず、VSはグレー表示します。
makoshichi

294

デフォルトでは、プロジェクトがデバッグモードでコンパイルされている場合、Visual StudioはDEBUGを定義し、リリースモードの場合は定義しません。RELEASEは、デフォルトではリリースモードでは定義されていません。このようなものを使用してください:

#if DEBUG
  // debug stuff goes here
#else
  // release stuff goes here
#endif

リリースモードでのみ何かを実行したい場合:

#if !DEBUG
  // release...
#endif

また、特定のシンボルが定義されている場合にのみ実行されるように[Conditional("DEBUG")]戻るメソッドで属性を使用できることも指摘する価値がありますvoid。シンボルが定義されていない場合、コンパイラーはこれらのメソッドへのすべての呼び出しを削除します。

[Conditional("DEBUG")]
void PrintLog() {
    Console.WriteLine("Debug info");
}

void Test() {
    PrintLog();
}

6
素晴らしい答え、感謝します。
Duy Tran

210

私は#defineディレクティブを探すよりもこのようにチェックすることを好みます:

if (System.Diagnostics.Debugger.IsAttached)
{
   //...
}
else
{
   //...
}

もちろん、警告があれば、デバッグモードで何かをコンパイルしてデプロイすることはできますが、デバッガーをアタッチしていません。


1
ありがとうございました!「#defines」が何であるかさえまだわからないので、これは素晴らしい解決策です!
ティム

そして私の場合、これはまさに私が望んでいることです。デバッガーが接続されている場合は実行したくないコードがあるため、デバッガーが接続されているかどうかを実際に知りたいのです。これはすごい!
JFTxJ 2013

1
個人的に#IF DEBUGは、持続してはならないデバッグコードの状況で使用したい場合。製品コードについては、上記の使用に同意します。
Coops

10
使用する代わりにこれを行うことの欠点#DEBUGは、このifステートメントがコード内にあり#DEBUG、コンパイル時に適用されないコードが回答によって削除されるため、常にチェックされ、ランタイムチェックと。 exe(またはコンパイルするもの)は小さいです。
Dan

1
@ user34660。述べられた質問に対する答えは「いいえ」であり、これは実際には誰の助けにもなりません。
Steve Smith、

51

私は#ifの大ファンではありません。特にコードベース全体に広げると、デバッグビルドはパスしますが、注意しないとリリースビルドが失敗するという問題が発生するためです。

だからここに私が思いついたものがあります(C#の#ifdefに触発されました):

public interface IDebuggingService
{
    bool RunningInDebugMode();
}

public class DebuggingService : IDebuggingService
{
    private bool debugging;

    public bool RunningInDebugMode()
    {
        //#if DEBUG
        //return true;
        //#else
        //return false;
        //#endif
        WellAreWe();
        return debugging;
    }

    [Conditional("DEBUG")]
    private void WellAreWe()
    {
        debugging = true;
    }
}

2
ちょっと今、それはかなり創造的です。属性を使用してプロパティを設定するのが好きです。
kenchilada 2013年

3
これには、現在の条件付き設定に基づいてコードを混乱させる可能性があるResharperのバグをリファクタリングすることで影響を受けないという利点があります。
Jafin 2013

3
私はこれが好きですが、なぜサービスの代わりにこれのシングルトン実装を作成しないのか疑問に思っています。これはシステム固有であり、どこにでも注入することを心配する必要がなくなります。(この機能の実装が異なるシナリオを想定できますか?
BastanteCaro 2015年

1
私が実際に使用している1つのクラスにシングルトンとサービスの実装があるので、それをどのように使用するかを選択できるようになります...もちろん、サービスの実装には、「スタブ」を出しやすくなるという利点があります。両方のコードパスをテストできること...
Tod Thomson

なぜDebuggingService静的クラスではなく、なぜインターフェースが必要なのでしょうか?これは、IoCコンテナでこれを使用することと関係がありますか?
ベン

23
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

メソッドにDebug.Assertは条件属性がありますDEBUG。定義されていない場合、呼び出しと割り当て isDebug = true削除されます。

シンボルが定義されている場合、呼び出しが含まれます。それ以外の場合、呼び出し(呼び出しのパラメーターの評価を含む)は省略されます。

DEBUGが定義されている場合、isDebugはに設定されますtrueDebug.Assertその場合は何も実行されません)に渡されます。


これもかなりクリエイティブなソリューションです。:)
ジャック

いいね。デバッグとリリースの間で変更する必要があるイテレーション変数の場合 var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
Matt Davis

19

ビルドタイプに定義された変数を使用しようとしている場合は、2行を削除する必要があります...

#define DEBUG  
#define RELEASE 

...これらは#if(DEBUG)を常に真にします。

また、RELEASEにはデフォルトの条件付きコンパイルシンボルはありません。定義する場合は、プロジェクトのプロパティに移動し、[ ビルド ]タブをクリックして、[ 一般]見出しの下の[ 条件付きコンパイルシンボル]テキストボックスにRELEASEを追加します。

他のオプションはこれを行うことです...

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif

7

上部の定義を削除します

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif

7

個別のクラスではなく静的関数としてのTod Thomsonによる回答のわずかに変更された(粗悪化された?)バージョン(既に含まれているviewutilsクラスからWebFormビューバインディングで呼び出すことができるようにしたかった)。

public static bool isDebugging() {
    bool debugging = false;

    WellAreWe(ref debugging);

    return debugging;
}

[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
    debugging = true;
}

6

プロジェクトのビルドプロパティで必ずDEBUG定数を定義してください。これにより、が有効になり#if DEBUGます。定義済みのRELEASE定数が表示されないので、DEBUGブロックにないものはすべてRELEASEモードである可能性があります。

プロジェクトのビルドプロパティでDEBUG定数を定義する


5

名前空間

using System.Resources;
using System.Diagnostics;

方法

   private static bool IsDebug()
    {
        object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
        if ((customAttributes != null) && (customAttributes.Length == 1))
        {
            DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
            return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
        }
        return false;
    }

3

多くの時間を節約できるヒント-たとえ選択してもそれを忘れないでください debugビルド構成の下でした(vs2012 / 13メニューではBUILD => CONFIGURATION MANAGERの下にあります)-十分ではありません。

そのため、PUBLISH Configurationに注意を払う必要があります。

ここに画像の説明を入力してください


0

これらのCOMPILERディレクティブの目的は、コード、デバッグコード、ベータコード、またはおそらくすべてのエンドユーザーに必要なコードを含めないようにコンパイラーに指示することです。必要に応じて、それらを含めたり、削除したりできます。たとえば、非AdDeptがAdDeptにマージされる場合、ソースコードを変更する必要はありません。次に、実行する必要があるのは、プログラムの既存のバージョンのコンパイラオプションプロパティページに#AdDeptディレクティブを含め、コンパイルして実行することだけです。マージされたプログラムのコードは生き生きとしています!。

プライムタイムの準備ができていないか、解放するまでコードでアクティブにできない新しいプロセスに宣言を使用することもできます。

とにかく、それが私のやり方です。


0

私はもっ​​と良い方法を考えなければなりませんでした。#ifブロックは他の構成で効果的にコメントであることがわかってきました(DEBUGまたはRELEASE;と仮定しますが、任意のシンボルに当てはまります)。

public class Mytest
    {
        public DateTime DateAndTimeOfTransaction;
    }

    public void ProcessCommand(Mytest Command)
        {
            CheckMyCommandPreconditions(Command);
            // do more stuff with Command...
        }

        [Conditional("DEBUG")]
        private static void CheckMyCommandPreconditions(Mytest Command)
        {
            if (Command.DateAndTimeOfTransaction > DateTime.Now)
                throw new InvalidOperationException("DateTime expected to be in the past");
        }

0

定義を削除し、条件がデバッグモードかどうかを確認します。ディレクティブがリリースモードであるかどうかを確認する必要はありません。

このようなもの:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.