根据 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.
对我来说,这就是
Conditional
属性仅改变单个方法调用级别的行为。但请考虑以下代码片段: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();
}
}
比较 Debug 和 Release 版本的输出:
调试发布
副作用!副作用!
副作用更大!副作用更大!
条件方法运行。
副作用!
副作用更大!
条件方法运行。
这种行为是否在某处指定? 我原以为两个版本都应该具有相同的输出,除了读取“条件方法运行”的行。
最佳答案
有趣的功能:-) 我从来没有注意到。
我看了一下IL。这并不能解释行为(编译过程),但我相信它无论如何都记录了结果。
整个 C# 代码行在 IL 中显然被遗漏了:
创建(x 变量),存储
在位置 0 并加载。然后
三种方法都适用
依次:DoSideEffects(),
DeMoreSideEffects() 和
条件方法()
对我来说,这真的是一个错误。似乎可以只排除 IL 中的 ConditionalMethod() 调用。但似乎你是对的,整条线都被遗漏了。
// 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
关于.net - ConditionalAttribute 应该去掉整行,还是只去掉方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3809129/