본문 바로가기
C#/이론

[예제로 배우는 C# 프로그래밍] 전처리기

by 단월໒꒱ 2022. 7. 6.

 

C# 전처리기

 

 

전처리기 지시어

 

  전처리기 지시어는 실제 컴파일이 시작되기 전에 컴파일러에게 특별한 명령을 미리 처리하도록 지시하는 것이다.

 

  모든 C# 전처리기 지시어는 #로 시작하며, 한 라인에 한 개의 전처리기 명령만을 사용한다. 또한, 전처리기 지시어는 C# Statement가 아니기 때문에 끝에 ;를 붙이지 않는다.

 

  전처리기 지시어는 해당 파일 안에서만 효력이 있다. 만약 하나의 클래스가 두 개의 파일에 나뉘어 Partial Class로 저장되었을 때, 두 개의 파일에서 동일한 심볼을 사용하고 싶다면, 두 개의 파일에 각각 심볼을 정의해야 한다.

 

 

 

조건별 컴파일

 

  C# 전처리기에서 자주 사용되는 것에는 #define, #if, #else, #endif 등이 있다.

 

  #define은 심볼을 정의할 때 사용된다. (ex. #define DEBUG)

  이렇게 정의된 심볼은 다른 전처리기 지시어에서 사용되기도 한다. (ex. #if (DEBUG))

 

  #define과 #if를 결합하여 조건별로 서로 다른 코드 블럭을 컴파일하도록 할 수 있다.

 

 

  다음 예제는 TEST_ENV라는 심볼이 정의되었는지 보고, 서로 다른 코드 블럭을 컴파일하는 코드이다.

 

 

#define TEST_ENV
//#define PROD_ENV

using System;

namespace App1
{
    class Program
    {
        static void Main(string[] args)
        {
            bool verbose = false;
            // ...

#if (TEST_ENV)
            Console.WriteLine("Test Environment: Verbose option is set.");
            verbose = true;
#else
            Console.WriteLine("Production");
#endif

            if (verbose)
            {
                //....
            }
        }
    }
}

 

 

 

region 전처리기 지시어

 

  #region은 실제로 많이 사용되는 지시어로, 코드 블럭을 논리적으로 묶을 때 유용하게 사용된다. 특히, 복잡하고 긴 클래스를 개념적으로 묶을 때 매우 유용하다.

 

  예를 들자면, public 메서드들만 묶어 [Public Methods]라고 명명할 수 있고, private 메서드들만 묶어 [Privates]라고 명명할 수 있다.

 

  #region은 #endregion과 쌍을 이루며 한 영역을 형성한다. #region 영역은 좌측에 +/-로 표시되어 expand/collapse할 수 있는 기능을 제공한다.

 

 

class ClassA
{
    #region Public Methods        
    public void Run() { }
    public void Create() { }        
    #endregion

    #region Public Properties
    public int Id { get; set; }
    #endregion

    #region Privates
    private void Execute() { }
    #endregion
}

 

 

 

기타 전처리기 지시어

 

  #undef : 지정된 심볼을 해제할 때 사용

  #elif : #if와 함께 사용하며 else if를 나타냄

  #line : 거의 사용 x, 라인번호를 임의로 변경하거나 파일명을 임의로 다르게 설정할 수 있게 해줌

  #error : 전처리시 preprocessing을 중단하고 에러 메세지 출력하게 함

  #warning : 경고 메세지를 출력하지만 preprocessing은 계속 진행함

 

 

// #warning 예제 -----------------------------------
#if (!ENTERPRISE_EDITION)
#warning This class should be used in Enterprise Edition
#endif

namespace App1 {
    class EnterpriseUtility {
    }
}

// #error 예제 --------------------------------------
#define STANDARD_EDITION
#define ENTERPRISE_EDITION

#if (STANDARD_EDITION && ENTERPRISE_EDITION)
#error Use either STANDARD or ENTERPRISE edition. 
#endif

namespace App1 {
    class Class1 {
    }
}

 

 

  warning 예제는 Enterprise Edition이 아닌 경우 경고 메세지를 내는 코드이다.

  error 예제는 Edition 심볼이 복수로 지정된 경우에 에러를 내게 하는 코드이다.

 

  만약 여러 개의 파일들을 병합한 후 컴파일을 할 경우에는 에러 체크가 유용할 수 있다.

 

 

 

pragma 전처리기 지시어

 

  #pragma 지시어는 위의 표준 C# 전처리기 지시어와 다르게, 컴파일러 제작업체가 고유하게 자신들의 것을 만들어 사용할 수 있는 지시어이다. 사용하는 컴파일러에 따라 지원되는 #pragma가 다르며, 개발자가 임의로 지정하여 사용할 수 있다.

 

  MS의 C# 컴파일러는 현재 #pragma warning과 #pragma checksum을 지원하고 있다.

     ① #pragma warning : 경고 메세지를 disable/enable하게 할 수 있음

     ② #pragma checksum : ASPX 페이지의 파일 체크섬을 생성할 때 사용

 

 

  다음 예제는 #pragma warning을 사용하여 컴파일시 CS3021 경고를 disable하고, if (false) 블럭에 대한 경고를 전체 disable 했다가 다시 enable하는 코드이다.

 

 

// CS3021 Warning을 Disable
#pragma warning disable 3021

namespace App1
{
    [System.CLSCompliant(false)] 
    class Program
    {
        static void Main(string[] args)
        {
            //...
        
#pragma warning disable
        if (false)
        {
            Console.WriteLine("TBD");
        }
#pragma warning restore
        
            //...
        }
    }
}

 

 

 

 

댓글