我有一段这样的代码:
//string
Session["LoggedInOk"] = "loginOk";
string value = Session["LoggedInOk"].ToString();
//bool
Session["LoggedInOk"] = true;
bool value = Session["LoggedInOk"] as bool;
//class
Book book = new Book();
Session["LoggedInOk"] = book;
Book value = Session["LoggedInOk"] as Book;
//datatable
DataTable table = new DataTable();
Session["LoggedInOk"] = table;
DataTable value = Session["LoggedInOk"] as DataTable;
如果我发布版本,编译器是否会对此进行优化?或者评估是否仍然存在,从而花费一些处理时间?
答案 0 :(得分:48)
是的,至少在Debug
电话中确实如此。我无法在这里看到JIT编译器是否也删除了if
的评估,但我想这是因为方程式没有任何副作用。
但是,您最好通过调用Debug.WriteLineIf
来保证安全,而Debug.WriteLine
并不依赖于JIT编译器来删除评估。
为了完整性,编译器可以删除.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 17 (0x11)
.maxstack 8
IL_0000: call string [mscorlib]System.Console::ReadLine()
IL_0005: ldstr "Ok"
IL_000a: call bool [mscorlib]System.String::op_Inequality(string,
string)
IL_000f: pop
IL_0010: ret
} // end of method Program::Main
。
发布版本中的代码:
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 42 (0x2a)
.maxstack 2
.locals init ([0] string state,
[1] bool V_1)
IL_0000: nop
IL_0001: call string [mscorlib]System.Console::ReadLine()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldstr "Ok"
IL_000d: call bool [mscorlib]System.String::op_Inequality(string,
string)
IL_0012: stloc.1
IL_0013: ldloc.1
IL_0014: brfalse.s IL_0029
IL_0016: nop
IL_0017: ldstr "Error occured: {0}"
IL_001c: ldloc.0
IL_001d: call string [mscorlib]System.String::Format(string,
object)
IL_0022: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_0027: nop
IL_0028: nop
IL_0029: ret
} // end of method Program::Main
Debug build中的代码:
Debug.WriteLine
如您所见,Release模式没有调用 #pragma pack(1)
struct Example
{
int foo;
QVector<int> bar;
};
,调试模式的位置。
答案 1 :(得分:15)
如果您使用
[Files] Source: "..\*.ext"; DestDir: "{tmp}\Test\"; \ AfterInstall: DoSomething; Flags: ignoreversion recursesubdirs createallsubdirs; [Code] procedure DoSomething; var Path: string; begin Path := CurrentFilename; { ... } end;
类中的方法来打印调试信息并使用断言检查逻辑,则可以使代码更加健壮,而不会影响运输产品的性能和代码大小。...
Debug
属性适用于ConditionalAttribute
的方法。支持Debug
的编译器忽略对这些方法的调用,除非“DEBUG”被定义为条件编译符号。
如您所见,编译器将忽略在非调试版本上对ConditionalAttribute
成员的任何调用。但是,它不会阻止程序检查您的if语句。如果您希望编译器也忽略if语句,您可以使用{{3}}将整个块括起来:
Debug
答案 2 :(得分:4)
语言规范要求C#编译器删除Debug
调用和对其参数的评估。
如果.NET JIT是一个复杂的JIT,它将确定字符串方法调用不是副作用,可以删除。 .NET JIT不是很复杂,所以它实际上仍有可能调用该方法。让我们来看看。
在发布模式下编译程序,对其进行反编译并在4.6.2上以x64运行,而不会调优器抑制优化。
static void Main()
{
var state = GetState();
if (state != "Ok")
{
Debug.WriteLine(state);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static string GetState()
{
return "x";
}
C#编译器保持字符串不等式调用完整:
我不确定规范是否允许对此进行优化,因为这可能是一种副作用方法。不确定允许编译器对其进行假设。
我们出色的JIT也没有删除电话:
(1)是GetState()
,(2)是string.!=
。
使用Debug.WriteLineIf
因为:
17.4.2.1条件方法 使用Conditional属性修饰的方法是条件方法。 Conditional属性通过测试条件编译符号来指示条件。根据是否在调用点定义了此符号,可以包含或省略对条件方法的调用。如果定义了符号,则包括呼叫;否则,将忽略呼叫(包括接收机的评估和呼叫参数)。