According to the documentation on the ConditionalAttribute
class:
Applying ConditionalAttribute to a method indicates to compilers that a call to the method should not be compiled into Microsoft intermediate language (MSIL) unless the conditional compilation symbol that is associated with ConditionalAttribute is defined.
To me this is saying that the Conditional
attribute only alters behavior at the individual method call level. But consider the following code snippet:
class InstanceType
{
public InstanceType DoSideEffects()
{
Console.WriteLine("Side effects!");
return this;
}
public InstanceType DoMoreSideEffects()
{
Console.WriteLine("More side effects!");
return this;
}
[Conditional("DEBUG")]
public void ConditionalMethod()
{
Console.WriteLine("Conditional method run.");
}
}
class Program
{
static void Main()
{
var x = new InstanceType();
// The compiler appears to strip out this entire line
// in a Release build.
x.DoSideEffects().DoMoreSideEffects().ConditionalMethod();
var y = new InstanceType();
// When each method call appears on its own line,
// the first two methods are included as expected.
y.DoSideEffects();
y.DoMoreSideEffects();
y.ConditionalMethod();
}
}
Compare the outputs of Debug and Release builds:
DEBUG RELEASE Side effects! Side effects! More side effects! More side effects! Conditional method run. Side effects! More side effects! Conditional method run.
Is this behavior specified somewhere? I had thought that both builds were supposed to have the same output except for the lines reading "Conditional method run."
Interessting feature :-) I've never noticed that.
I've taken a look at the IL. This doesn't explain the behaviour (the compilation process), but it documents the result anyway, I believe.
The whole C# code line is clearly left out in the IL:
To me, this looks like a bug, really. It seems that it would have been possible to just exclude the ConditionalMethod() call in the IL. But it seems that you are right, that the whole line is left out.
// DEBUG compilation
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 58 (0x3a)
.maxstack 1
.locals init (class ConsoleApplication3.InstanceType V_0,
class ConsoleApplication3.InstanceType V_1)
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication3.InstanceType::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects()
IL_000d: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects()
IL_0012: callvirt instance void ConsoleApplication3.InstanceType::ConditionalMethod()
IL_0017: nop
IL_0018: newobj instance void ConsoleApplication3.InstanceType::.ctor()
IL_001d: stloc.1
IL_001e: ldloc.1
IL_001f: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects()
IL_0024: pop
IL_0025: ldloc.1
IL_0026: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects()
IL_002b: pop
IL_002c: ldloc.1
IL_002d: callvirt instance void ConsoleApplication3.InstanceType::ConditionalMethod()
IL_0032: nop
IL_0033: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0038: pop
IL_0039: ret
} // end of method Program::Main
// RELEASE compilation
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 33 (0x21)
.maxstack 1
.locals init ([0] class ConsoleApplication3.InstanceType y)
IL_0000: newobj instance void ConsoleApplication3.InstanceType::.ctor()
IL_0005: pop
IL_0006: newobj instance void ConsoleApplication3.InstanceType::.ctor()
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoSideEffects()
IL_0012: pop
IL_0013: ldloc.0
IL_0014: callvirt instance class ConsoleApplication3.InstanceType ConsoleApplication3.InstanceType::DoMoreSideEffects()
IL_0019: pop
IL_001a: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_001f: pop
IL_0020: ret
} // end of method Program::Main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With