큰 프로젝트에서 사용하는 것이 더 나은 이유는 무엇입니까?
#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 DEBUG 예제 : WCF 통신을 위해 다른 바인딩을 설정하려고 할 때 사용합니다.
#if DEBUG
public const String ENDPOINT = "Localhost";
#else
public const String ENDPOINT = "BasicHttpBinding";
#endif
첫 번째 예에서는 코드가 모두 존재하지만 DEBUG가 설정되어 있지 않으면 무시됩니다. 두 번째 예에서 const ENDPOINT는 DEBUG 설정 여부에 따라 "Localhost"또는 "BasicHttpBinding"으로 설정됩니다.
업데이트 : 중요하고 까다로운 요점을 명확히하기 위해이 답변을 업데이트하고 있습니다. 를 사용하기로 선택한 경우 에는 런타임이 아니라ConditionalAttribute
컴파일 중에 호출이 생략 됩니다 . 그건:
MyLibrary.dll
[Conditional("DEBUG")]
public void A()
{
Console.WriteLine("A");
B();
}
[Conditional("DEBUG")]
public void B()
{
Console.WriteLine("B");
}
라이브러리가 릴리즈 모드 (예 : 디버그 기호)에 대해 컴파일 할 때, 그것은 영원히에 전화를해야합니다 B()
내에서 A()
, 생략해도에 전화 A()
DEBUG 어셈블리 호출에 정의되어 있기 때문에 포함되어 있습니다.
글쎄, 그것들이 전혀 같은 것을 의미하지 않는다는 점은 주목할 가치가 있습니다.
DEBUG 기호가 정의되지 않은 경우 첫 번째 경우에는 SetPrivateValue
자체 호출되지 않지만 두 번째 경우에는 존재하지만 DEBUG 기호없이 컴파일 된 호출자 는 해당 호출을 생략합니다.
코드와 모든 호출자가 동일한 어셈블리에있는 경우이 차이는 덜 중요합니다. 그러나 첫 번째 경우 에도 호출 코드 #if DEBUG
주위 에 있어야 합니다.
개인적으로 두 번째 방법을 권장하지만 머리의 차이점을 명확하게 유지해야합니다.
나는 많은 의견에 동의하지 않을 것이라 확신하지만, 빌드 녀석으로서 "하지만 내 컴퓨터에서 작동합니다!" 테스트 및 디버깅에 실제로 필요한 것이 있으면 테스트 가능성을 실제 프로덕션 코드와 분리하는 방법을 찾으십시오.
단위 테스트에서 조롱하여 시나리오를 추상화하고 테스트하려는 하나의 오프 시나리오에 대해 일회성 버전을 작성하지만 프로덕션 릴리스를 위해 테스트하고 작성한 바이너리의 코드에는 디버그 테스트를 넣지 마십시오. 이 디버그 테스트는 개발자로부터 가능한 버그를 숨기므로 나중에 프로세스에서 찾을 수 없습니다.
#if debug
코드에 왜 또는 유사한 구성 이 필요 합니까?
#if DEBUG
에서 프로세스의 일부로 이메일을 전송해야하는 시스템을 테스트하는 동안 실수로 다른 사람을 스팸하지 않도록하기 위해 디버그 빌드에서 자신에게 기본 수신자 이메일을 설정하는 것과 같은 작업을 종종 수행 합니다. 때로는 이러한 작업에 적합한 도구가 있습니다 :)
첫 번째 예제로, SetPrivateValue
경우 빌드에 존재하지 않습니다 DEBUG
정의되지 않은 두 번째 예제로, 호출 에 SetPrivateValue
경우 빌드에 존재하지 않습니다 DEBUG
정의되어 있지 않습니다.
첫 번째 예를 들어, 당신은 어떤 통화를 포장해야 SetPrivateValue
와 함께 #if DEBUG
뿐만 아니라.
두 번째 예에서는 호출 SetPrivateValue
이 생략되지만 SetPrivateValue
여전히 컴파일됩니다. 이것은 라이브러리를 빌드 할 때 유용하므로 라이브러리를 참조하는 응용 프로그램이 여전히 조건을 충족하는 경우 함수를 사용할 수 있습니다.
통화를 생략하고 수신자의 공간을 절약하려면 다음 두 가지 기술을 조합하여 사용할 수 있습니다.
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
#if DEBUG
// method body here
#endif
}
#if DEBUG
주변에 Conditional("DEBUG")
아직도 (컴파일 오류가) 존재하지 않는 함수를 호출하는 데 문제가있는, 그래서 그냥 alltogether IL에서 기능을 제거하고, 그 함수에 대한 호출을 제거하지 않습니다.
custom을 사용하여 네트워크 트래픽을 기록하는 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
}