大規模なプロジェクトでは、どちらを使用するのが適切で、その理由は次のとおりです。
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
または
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
大規模なプロジェクトでは、どちらを使用するのが適切で、その理由は次のとおりです。
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
または
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
回答:
それは本当にあなたが何をしようとしているのかに依存します:
#if DEBUG
:ここのコードはリリース時にILに到達しません。[Conditional("DEBUG")]
:このコードは、ILに到達するであろう、しかし呼び出し、呼び出し側のコンパイル時にDEBUGが設定されていない限り省略する方法に。個人的に私は状況に応じて両方を使用します:
Conditional( "DEBUG")例:これを使用して、後でリリース中にコードを戻って編集する必要がないようにしますが、デバッグ中はタイプミスがないことを確認したいと思います。この関数は、INotifyPropertyChangedでプロパティ名を使用するときに、プロパティ名を正しく入力したことを確認します。
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected void VerifyPropertyName(String propertyName)
{
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
Debug.Fail(String.Format("Invalid property name. Type: {0}, Name: {1}",
GetType(), propertyName));
}
#if DEBUG
同じ関数でその関数へのすべての呼び出しをラップすることをいとわないのでない限り、実際にはを使用して関数を作成したくありません#if DEBUG
。
#if DEBUG
public void DoSomething() { }
#endif
public void Foo()
{
#if DEBUG
DoSomething(); //This works, but looks FUGLY
#endif
}
対:
[Conditional("DEBUG")]
public void DoSomething() { }
public void Foo()
{
DoSomething(); //Code compiles and is cleaner, DoSomething always
//exists, however this is only called during DEBUG.
}
#ifデバッグの例: WCF通信用に異なるバインディングをセットアップしようとするときにこれを使用します。
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
最初の例では、コードはすべて存在しますが、DEBUGがオンでない限り無視されます。2番目の例では、DEBUGが設定されているかどうかに応じて、const ENDPOINTが「Localhost」または「BasicHttpBinding」に設定されます。
更新:重要でトリッキーなポイントを明確にするために、この回答を更新しています。を使用する場合はConditionalAttribute
、ランタイムではなく、コンパイル時に呼び出しが省略されることに注意してください。あれは:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
ライブラリがリリースモード(すなわち無DEBUGシンボル)に対してコンパイルされたとき、それは永遠に電話を持つことになりますB()
の中からA()
、省略した場合でもにコールA()
DEBUGは、アセンブリの呼び出しで定義されているので、含まれています。
まあ、それらがまったく同じことを意味しないことは注目に値します。
DEBUGシンボルが定義されていない場合、最初のケースではSetPrivateValue
それ自体は呼び出されません... 2番目のケースではそれは存在しますが、DEBUGシンボルなしでコンパイルされた呼び出し元はそれらの呼び出しを省略します。
コードとそのすべての発信者が同じアセンブリ内にある場合、この違いはそれほど重要な-しかし、それは最初のケースでは、あなたがいることを意味も持っている必要があります#if DEBUG
周りの呼び出しにもコードを。
個人的には2番目のアプローチをお勧めしますが、両者の違いを頭の中で明確にしておく必要があります。
私は多くの点で私に同意しないと確信していますが、ビルド担当者として時間を費やして「しかし、それは私のマシンで動作します!」テストとデバッグに何かが本当に必要な場合は、そのテスト容易性を実際の製品コードから分離する方法を考えてください。
単体テストでモックを使用してシナリオを抽象化し、テストする1回限りのシナリオの1回限りのバージョンを作成します。ただし、本番リリース用にテストおよび作成するバイナリのコードにデバッグ用のテストを挿入しないでください。これらのデバッグテストは、可能性のあるバグを開発者から隠すだけなので、プロセスの後半まで発見されません。
#if debug
コードまたは同様の構成がコードに必要なのでしょうか。
#if DEBUG
ます。これにより、プロセスの一部として電子メールを送信する必要があるシステムをテストするときに、誤って他人にスパムを送信しないようにします。時々これらは仕事のための適切なツールです:)
最初の例でSetPrivateValue
は、がDEBUG
定義されていない場合はビルドに存在しません。2番目の例では、SetPrivateValue
がDEBUG
定義されていない場合、への呼び出しはビルドに存在しません。
最初の例では、への呼び出しも同様にラップする必要がSetPrivateValue
あり#if DEBUG
ます。
2番目の例では、への呼び出しSetPrivateValue
は省略されますが、SetPrivateValue
それ自体は引き続きコンパイルされることに注意してください。これは、ライブラリを構築する場合に役立ちます。そのため、ライブラリを参照するアプリケーションは、引き続き関数を使用できます(条件が満たされた場合)。
呼び出しを省略して呼び出し先のスペースを節約したい場合は、次の2つの方法を組み合わせて使用できます。
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
#if DEBUG
れConditional("DEBUG")
ません。ILから関数が完全に削除されるだけなので、存在しない関数の呼び出しが残っています(コンパイルエラー)。
#else
Jon Skeetのポイントの1つに対処するnullスタブ関数を定義するステートメントもコードにあると仮定しましょう。2つの間に2つ目の重要な違いがあります。
仮定#if DEBUG
やConditional
機能はメインプロジェクトの実行可能ファイルによって参照されるDLLに存在します。を使用する#if
と、ライブラリのコンパイル設定に関して条件付きの評価が実行されます。Conditional
属性を使用して、呼び出し元のコンパイル設定に関して条件の評価が実行されます。
カスタムを使用してネットワークトラフィックをログに記録するSOAP WebService拡張機能があります[TraceExtension]
。これはデバッグビルドにのみ使用し、リリースビルドからは省略します。を使用し#if DEBUG
て[TraceExtension]
属性をラップし、リリースビルドから削除します。
#if DEBUG
[TraceExtension]
#endif
[System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )]
[ more attributes ...]
public DatabaseResponse[] GetDatabaseResponse( ...)
{
object[] results = this.Invoke("GetDatabaseResponse",new object[] {
... parmeters}};
}
#if DEBUG
[TraceExtension]
#endif
public System.IAsyncResult BeginGetDatabaseResponse(...)
#if DEBUG
[TraceExtension]
#endif
public DatabaseResponse[] EndGetDatabaseResponse(...)
通常は、非デバッグコードでデバッグを実行するか、ほとんどがWindowsサービスで実行するかを決定するProgram.csで必要になります。そこで、読み取り専用フィールドIsDebugModeを作成し、その値を以下に示すように静的コンストラクターに設定しました。
static class Program
{
#region Private variable
static readonly bool IsDebugMode = false;
#endregion Private variable
#region Constrcutors
static Program()
{
#if DEBUG
IsDebugMode = true;
#endif
}
#endregion
#region Main
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
if (IsDebugMode)
{
MyService myService = new MyService(args);
myService.OnDebug();
}
else
{
ServiceBase[] services = new ServiceBase[] { new MyService (args) };
services.Run(args);
}
}
#endregion Main
}