[ACCEPTED]-How does the Conditional attribute work?-conditional-compilation
This is controlled by the compiler. All 30 methods with [Conditional]
will still be included in 29 the MSIL, but will include a .custom instance
line that 28 details the [Conditional]
. At compile time for a method 27 caller the compiler lexes, then does semantic 26 analysis and overload resolution, and finds 25 the .custom instance
IL in the method you placed [Conditional]
on. It 24 therefore doesn't compile the call.
So: the 23 compiler compiles the target method, but 22 does not compile any call to that method. Note: the method is still 21 there and you could still call it with reflection. See 20 the spec
Calls to a conditional method are either 19 included or omitted depending on whether 18 this symbol is defined at the point of the 17 call. If the symbol is defined, the call 16 is included; otherwise, the call (including 15 evaluation of the receiver and parameters 14 of the call) is omitted.
How can you verify 13 it? Fire up the developer command prompt, type 12 ildasm <enter>
and open the relevant dlls/exes. Check 11 out the caller and the called [Conditional]
methods. You'll 10 see the called methods have the extra IL 9 with .custom instance
, and the caller lines are omitted 8 where you would expect. Try it on a console 7 application with the code below.
Why? It 6 makes conditional calls simpler in some 5 cases than using #if
. See Eric Lippert: What's the difference between conditional compilation and the conditional attribute?
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?");
}
}
And in the corresponding 4 MSIL, VerboseEmit
is included, but not called from 3 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
Bonus points. Look at the console output 2 and the MSIL for this (modify the Emit methods 1 accordingly):
static void Main(string[] args)
{
int callCount = 0;
AlwaysEmit(++callCount);
VerboseEmit(++callCount);
DebugEmit(++callCount);
Console.WriteLine("Call count = " + callCount);
Console.ReadLine();
}
(Have debated whether this qualifies as an answer or not, but feel it's worth mentioning. If people disagree with DVs or comments, I'll happily delete)
One important feature of the fact that 16 this affects call-sites and not the methods 15 themselves is that this feature works across assemblies, and 14 it's the compilation symbols that are in 13 scope for the call site that affects whether 12 the call is invoked.
So one reason why the 11 actual methods have to be emitted into the 10 compiled assembly is because, at that time, it's 9 not actually known whether the method is 8 going to be invoked.
It's at the later point 7 in time, when the consuming application 6 is being compiled, that we actually know 5 whether the method is used or not. This 4 also means that in a complex solution, where 3 there are multiple consumers at multiple 2 levels, some of the calls may happen (in some 1 projects) and others will not.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.