How does the Conditional attribute work?

I have helper methods noted [Conditional("XXX")]. The goal is to make methods conditionally compiled when only the conditional compilation symbol XXX is present. We use this for debugging and tracking functionality, and it works very well.

During my research on how conditional compilation works, I found that several sources indicating methods marked with an attribute Conditionalwould be placed in IL, but method calls would not be executed.

How is code compiled in IL but not executed? How can I verify that the behavior is actually described like this? I did not do much with IL, so my skills are a little weak in this area.

+4
source share
2 answers

This is controlled by the compiler. All methods with [Conditional]will continue to be included in MSIL, but will include a string .custom instancethat describes in detail [Conditional]. At compile time, for the compiler’s vocabulary method handler, it then performs semantic analysis and overload resolution, and finds the .custom instanceIL in the method that you placed [Conditional]on. Therefore, it does not compile the call.

So: the compiler compiles the target method, but does not compile the call to this method. Note: the method still exists, and you can still call it reflection. See specification

, . , ; ( ) .

? , ildasm <enter> dlls/exes. [Conditional]. , IL .custom instance, , . .

? , #if. . : ?

class Program
{
    static void Main(string[] args)
    {
        AlwaysEmit();
        DebugEmit();
        VerboseEmit();
    }

    public static void AlwaysEmit()
    {
        Console.WriteLine("Beam me up");
    }

    [Conditional("DEBUG")]
    public static void DebugEmit()
    {
        Console.WriteLine("Kirk out");
    }

    [Conditional("VERBOSE")]
    public static void VerboseEmit()
    {
        Console.WriteLine("Say that again?");
    }
}

MSIL VerboseEmit , Main:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  call       void RateScope.SdrApi.UploaderConsoleApp.Program::AlwaysEmit()
  IL_0006:  nop
  IL_0007:  call       void RateScope.SdrApi.UploaderConsoleApp.Program::DebugEmit()
  IL_000c:  nop
  IL_000d:  ret
} // end of method Program::Main

...

.method public hidebysig static void  VerboseEmit() cil managed
{
  .custom instance void [mscorlib]System.Diagnostics.ConditionalAttribute::.ctor(string)
     = ( 01 00 07 56 45 52 42 4F 53 45 00 00 ) // ...VERBOSE..
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Say that again\?"
  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Program::VerboseEmit

. MSIL ( Emit):

static void Main(string[] args)
{
    int callCount = 0;
    AlwaysEmit(++callCount);
    VerboseEmit(++callCount);
    DebugEmit(++callCount);
    Console.WriteLine("Call count = " + callCount);
    Console.ReadLine();
}
+6

(, , , . DV , )

, -, , , , , , .

, , , , .

, , , . , , , ( ), - .

+4

Source: https://habr.com/ru/post/1541776/


All Articles