developer tip

전 처리기의 C # 매크로 정의

copycodes 2020. 11. 27. 08:21
반응형

전 처리기의 C # 매크로 정의


C #은 전 처리기 문을 사용하여 C 프로그래밍 언어에서 수행되는 것처럼 매크로를 정의 할 수 있습니까? 다음과 같이 반복되는 특정 문을 정기적으로 입력하는 것을 단순화하고 싶습니다.

Console.WriteLine("foo");

아니요, C #은 C와 같은 전 처리기 매크로를 지원하지 않습니다 . 반면에 Visual Studio에는 스 니펫이 있습니다. Visual Studio의 코드 조각은 IDE의 기능이며 컴파일시 코드에서 전처리기에 의해 대체되지 않고 편집기에서 확장됩니다.


mcpp와 같은 C 전처리기를 사용하여 .csproj 파일에 리깅 할 수 있습니다. 그런 다음 Compile에서 Preprocess로 또는 호출하는 모든 소스 파일에 대한 "빌드 작업"을 변경합니다. 다음과 같이 BeforBuild 를 .csproj에 추가 하십시오.

  <Target Name="BeforeBuild" Inputs="@(Preprocess)" Outputs="@(Preprocess->'%(Filename)_P.cs')">
<Exec Command="..\Bin\cpp.exe @(Preprocess) -P -o %(RelativeDir)%(Filename)_P.cs" />
<CreateItem Include="@(Preprocess->'%(RelativeDir)%(Filename)_P.cs')">
  <Output TaskParameter="Include" ItemName="Compile" />
</CreateItem>

적어도 하나의 파일 (텍스트 편집기에서)에서 Compile to Preprocess를 수동으로 변경해야 할 수 있습니다. 그러면 Visual Studio에서 "Preprocess"옵션을 선택할 수 있습니다.

매크로가 많이 남용되고 오용된다는 것을 알고 있지만 완전히 제거하는 것은 나쁘지는 않더라도 똑같이 나쁩니다. 매크로 사용의 전형적인 예는 NotifyPropertyChanged 입니다. 이 코드를 수천 번 손으로 다시 작성해야했던 모든 프로그래머는 매크로 없이는 얼마나 고통 스러운지 알고 있습니다.


나는 이것을 피하기 위해 사용합니다 Console.WriteLine(...).

public static void Cout(this string str, params object[] args) { 
    Console.WriteLine(str, args);
}

다음을 사용할 수 있습니다.

"line 1".Cout();
"This {0} is an {1}".Cout("sentence", "example");

간결하고 펑키합니다.


매크로를 작성할 수는 없지만 예제와 같은 것을 단순화 할 때 C # 6.0은 이제 정적 사용을 제공합니다. 다음은 Martin Pernica가 미디엄 기사 에서 제시 한 예입니다 .

using static System.Console; // Note the static keyword

namespace CoolCSharp6Features
{
  public class Program
  {
    public static int Main(string[] args)
    {
      WriteLine("Hellow World without Console class name prefix!");

      return 0;
    }
  }
}

C #의 C 스타일 매크로에 직접 해당하는 것은 없지만 / / pragma inline가 있거나없는 d 정적 메서드 가 가장 가까운 방법입니다.#if#elseif#else

        /// <summary>
        /// Prints a message when in debug mode
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void Log(object message) {
#if DEBUG
            Console.WriteLine(message);
#endif
        }

        /// <summary>
        /// Prints a formatted message when in debug mode
        /// </summary>
        /// <param name="format">A composite format string</param>
        /// <param name="args">An array of objects to write using format</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void Log(string format, params object[] args) {
#if DEBUG
            Console.WriteLine(format, args);
#endif
        }

        /// <summary>
        /// Computes the square of a number
        /// </summary>
        /// <param name="x">The value</param>
        /// <returns>x * x</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double Square(double x) {
            return x * x;
        }

        /// <summary>
        /// Wipes a region of memory
        /// </summary>
        /// <param name="buffer">The buffer</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void ClearBuffer(ref byte[] buffer) {
            ClearBuffer(ref buffer, 0, buffer.Length);
        }

        /// <summary>
        /// Wipes a region of memory
        /// </summary>
        /// <param name="buffer">The buffer</param>
        /// <param name="offset">Start index</param>
        /// <param name="length">Number of bytes to clear</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static unsafe void ClearBuffer(ref byte[] buffer, int offset, int length) {
            fixed(byte* ptrBuffer = &buffer[offset]) {
                for(int i = 0; i < length; ++i) {
                    *(ptrBuffer + i) = 0;
                }
            }
        }

이것은 매크로처럼 완벽하게 작동하지만 약간의 단점 inline이 있습니다. d 로 표시된 메서드는 다른 "일반"메서드와 마찬가지로 어셈블리의 리플렉션 부분에 복사됩니다.


다행히 C #에는 C / C ++ 스타일의 전처리 기가 없습니다. 조건부 컴파일과 pragma (그리고 내가 기억할 수없는 다른 것) 만 지원됩니다. 불행히도 C #에는 메타 프로그래밍 기능이 없습니다 ( 실제로 귀하의 질문과 어느 정도 관련 있을 수 있습니다 ).


클래스에서 C 매크로를 C # 정적 메서드로 전환합니다.


다음과 같이 확장 기능을 작성하는 것이 좋습니다.

public static class WriteToConsoleExtension
{
   // Extension to all types
   public static void WriteToConsole(this object instance, 
                                     string format, 
                                     params object[] data)
   {
       Console.WriteLine(format, data);
   }
}

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        // Usage of extension
        p.WriteToConsole("Test {0}, {1}", DateTime.Now, 1);
    }
}

이것이 도움이되기를 바랍니다 (너무 늦지 않았습니다 :))


Since C# 7.0 supports using static directive and Local functions you don't need preprocessor macros for most cases.

참고URL : https://stackoverflow.com/questions/709463/c-sharp-macro-definitions-in-preprocessor

반응형