我习惯把代码写成(只是一个例子)
Request.QueryString["xxxx"] != null
最近有人说
null != Request.QueryString["xxxx"]
提供更好的性能。
我很想知道它是否真的带来了任何区别,如果有的话,如何?
注意~以上只是一个例子。笼统地说
无论
Constant [Operator] Actual Value (e.g. 1 == Convert.ToInt32(textbox1.text))
比
Actual Value [Operator] Constant (e.g. Convert.ToInt32(textbox1.text) == 1)
谢谢
最佳答案
什么
这是一种用于具有许多隐式类型转换的语言的编码风格(由于他的 OSV 词序,因此友好地命名为来自星球大战角色的 Yoda)。有时它甚至被项目指南强制执行和要求,以防止由于拼写错误而导致的某种错误。不同的语言对这种风格有不同的变体和扩展,但我将把这个答案限制在 C 和 C#。
为什么是
例如在 C 中你可以写:
int a = CalculateValue();
if (a = CalculateAnotherValue()) {
/* Do something */
}
此代码将分配给
a
从 CalculateValue()
返回的值然后它将用 CalculateAnotherValue()
的结果覆盖该值如果它不为零,那么它将执行代码。可能这不是我们打算做的,也不是 if
中的任务。表达是错误的。从你的例子 NULL
那么你可能有:if (pBuffer = NULL)
同样,这可能不是您想要的(这是一个很常见的错误),您会将 NULL 分配给指针,并且条件将始终为假。如果你写:
if (NULL = pBuffer)
它不会编译(因为您无法为文字赋值)并且您将收到编译时错误。
这种编译时检查并不是使用这种编码风格的唯一原因,看看这个 C#(很常见)代码:
if (text != null && text.Equals("something", StringComparison.InvariantCulture)
DoSomething();
它可以签约为:
if ("something".Equals(text, StringComparison.InvariantCulture))
DoSomething();
为什么不
在 C# 中通常没有关系。这是从 C/C++ 继承的实践。因为在 C# 中表达式不会自动转换为
bool
那么以下代码将无法编译:if (Request.QueryString["PartnerID"] = null)
那么这种做法在 C# 中是没有用的(@IlianPinzon 在评论中指出的异常(exception)),它只用于避免此类错误的性能。
关于为什么是部分中的最后一个例子,问题是可读性,写
"something".Equals(text)
喜欢说“如果那个人快乐”而不是“如果那个人快乐”。表现
从这些函数开始:
static bool TestRight(object value)
{ return value == null; }
static bool TestLeft(object value)
{ return null == value; }
他们产生以下IL:
.maxstack 2
.locals init ([0] bool CS$1$0000)
L_0000: nop
L_0001: ldnull
L_0002: ldarg.0
L_0003: ceq
L_0005: stloc.0
L_0006: br.s L_0008
L_0008: ldloc.0
L_0009: ret
唯一的区别在于 L_0001 和 L_0002 行,它们只是交换了但其操作数的顺序不会改变
ceq
的行为.即使您覆盖 Equals()
JIT 编译器将为两个表达式生成相同的汇编代码(因为比较总是由 Equals()
完成,null
是无类型的)。如果比较涉及用户定义的相等比较器,事情可能会更加复杂,在这种情况下,没有规则,它将取决于有效的
op_Equals
执行。例如这个 ==
执行:public static bool operator==(MyType lhs, MyType rhs)
{
if (Object.ReferenceEquals(lhs, rhs))
return true;
if (Object.ReferenceEquals(lhs, null))
return false;
return lhs.Equals(rhs);
}
在这种情况下,如果第一个操作数是
null
执行速度会稍微快一些(因为 MyType.Equals()
甚至不会被调用)但是这种性能增益非常小:您节省了一次比较、很少的跳转和一个虚函数调用。此外,您可以在相反的情况下将函数重写为更快(如果您真的对此很重要)。这里有一个小测试
MyType.Equals(object)
只需返回 true
对于任何非 null
范围。测试将循环Int32.MaxValue
次:操作总时间(毫秒)
lhs == null 10521
null == lhs 2346
似乎是“优化”版本,可避免不必要的调用
Equals()
速度快了五倍,但请注意循环计数非常高,而且 Equals()
的实际实现为空,真正的实现将减少函数调用的相对开销(并且可能除了这个 微优化 之外,您还有其他事情要做)。对于系统类,您不能依赖此详细信息,例如 String.Equals()
将始终由运算符(operator)调用(无论顺序如何),但您不能假设一个代码路径更快,而且这一事实在框架的 future 版本中(或对于不同的 CPU 架构)不会改变。
关于c# - 在对文字值进行相等比较时,操作数的顺序重要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10811410/