C # if / then 지시어 대 디버그 대 릴리스


433

솔루션 속성에서 하나의 유일한 프로젝트에 대해 구성을 "릴리스"로 설정했습니다.

메인 루틴의 시작 부분 에이 코드가 있으며 "Mode = Debug"가 표시됩니다. 또한 맨 위에 두 줄이 있습니다.

#define DEBUG 
#define RELEASE

올바른 변수를 테스트하고 있습니까?

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

내 목표는 디버그 모드와 릴리스 모드를 기반으로 변수에 다른 기본값을 설정하는 것입니다.


13
디버그 및 릴리스를 모두 정의하고 있습니다.
Eric Dahlvang

답변:


719

DEBUG/ _DEBUG는 이미 VS에 정의되어 있어야합니다.

#define 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 # #ifdef은 C / C ++의 전처리 기에 국한된 것이 아니라 C #에 대해 이야기하고 있음을 기억하십시오 #if.
jduncanator

27
@Jess, 나는하지 ReSharper에서이가 회색 처리하고 Visual Studio를 믿는다
Dakotah Hicock

1
@DakotahHicock 맞습니다, 나는 resharper를 사용하지 않고 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"가 무엇인지 모르기 때문에 이것이 훌륭한 솔루션입니다!
Tim

그리고 내 경우에는 이것이 내가 원하는 것을 정확하게 수행합니다. 디버거가 연결되어 있으면 실행하고 싶지 않은 코드가 있다는 것을 알고 있기 때문에 실제로 디버거가 연결되어 있는지 알고 싶습니다. 대단해!
JFTxJ

1
개인적 #IF DEBUG으로 디버깅 코드가 사용되지 않는 상황에서 사용 하는 것이 좋습니다. 프로덕션 코드의 경우 위의 사용에 동의합니다.
Coops

10
사용하는 대신이 작업을 수행하는 것에 대한 단점은 #DEBUGthis 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

3
이것은 현재 조건부 설정에 따라 코드를 망칠 수있는 Resharper의 버그를 리팩토링하여 적중하지 않는 이점이 있습니다.
Jafin

3
나는 이것을 좋아하지만 왜 서비스 대신 이것을 위해 싱글 톤 구현을 만들지 않는지 궁금합니다. 시스템에 따라 다르므로 어디에나 주입하는 것에 대해 걱정할 필요가 없습니다. (이 기능의 구현이 다른 시나리오를 상상할 수 있습니까?
BastanteCaro

1
실제로 사용중인 한 클래스에 싱글 톤 및 서비스 구현이 있으므로이를 사용하는 방법을 선택할 수 있습니다. 물론 서비스 구현은 "스텁"하기가 더 쉽다는 이점이 있습니다. 두 코드 경로를 모두 테스트 할 수 있습니다 ...
Tod Thomson

DebuggingService정적 클래스가 아니며 왜 인터페이스가 필요한지 궁금합니다. 이것이 IoC 컨테이너와 함께 사용하는 것과 관련이 있습니까?
Ben

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

이 메소드 Debug.Assert에는 조건부 속성이 DEBUG있습니다. 정의되지 않은 경우 통화 및 할당 isDebug = true제거됩니다 .

기호가 정의되면 통화가 포함됩니다. 그렇지 않으면 호출 (호출 매개 변수 평가 포함)이 생략됩니다.

경우 DEBUG정의, isDebug로 설정 true(및 전달 Debug.Assert이 경우에 아무것도 안하는).


이것은 또한 매우 창의적인 솔루션입니다. :)
Jack

좋은. 디버그와 릴리스 사이에서 변경해야하는 반복 변수의 경우 ... var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
Matt Davis

19

빌드 유형에 정의 된 변수를 사용하려는 경우 두 줄을 제거해야합니다.

#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빌드 구성 (2012/13 메뉴에서 BUILD => CONFIGURATION MANAGER 아래에 있음)에서 선택하더라도 충분하지 않습니다.

다음 Configuration과 같이 PUBLISH에주의해야합니다 .

여기에 이미지 설명을 입력하십시오


0

이러한 COMPILER 지시문의 목적은 컴파일러에게 광고 부서 (예 : #Define AdDept)를 제외한 모든 최종 사용자가 필요로하는 코드, 디버그 코드, 베타 코드 또는 코드를 포함하지 않도록 지시하는 것입니다. 필요에 따라 포함하거나 제거 할 수 있습니다. 예를 들어 비 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.