我习惯把代码写成(只是一个例子)
Request.QueryString["xxxx"] != null
Run Code Online (Sandbox Code Playgroud)
最近有人这么说
null != Request.QueryString["xxxx"]
Run Code Online (Sandbox Code Playgroud)
提供更好的表现.
我很想知道它是否真的带来了任何不同,如果是这样的话怎么样?
注意〜以上只是一个例子.一般来说
是否
Constant [Operator] Actual Value (e.g. 1 == Convert.ToInt32(textbox1.text))
Run Code Online (Sandbox Code Playgroud)
比...更好
Actual Value [Operator] Constant (e.g. Convert.ToInt32(textbox1.text) == 1)
Run Code Online (Sandbox Code Playgroud)
谢谢
Adr*_*tti 15
这是一种用于具有许多隐式类型转换的语言的编码风格(由于他的OSV单词顺序,友好地命名为星球大战角色的Yoda ).有时它甚至被项目指南强制执行和要求,以防止从拼写错误中产生某种错误.不同的语言有这种风格的不同变化和扩展,但我将这个答案限制在C和C#.
例如在C中你可以写:
int a = CalculateValue();
if (a = CalculateAnotherValue()) {
/* Do something */
}
Run Code Online (Sandbox Code Playgroud)
此代码将分配给a从此返回的值,CalculateValue()它将用结果覆盖该值,CalculateAnotherValue()如果它不为零,则它将执行代码.可能它不是打算做的,if表达式中的赋值是错误的.从你的例子中NULL你可能有:
if (pBuffer = NULL)
Run Code Online (Sandbox Code Playgroud)
再次可能它不是你想要的(这是一个非常常见的错误),你将指定NULL指针,条件将始终为false.如果你写:
if (NULL = pBuffer)
Run Code Online (Sandbox Code Playgroud)
它不会编译(因为你不能为文字赋值),你会得到一个编译时错误.
这种编译时间检查不是使用这种编码风格的唯一原因,看看这个C#(非常常见)的代码:
if (text != null && text.Equals("something", StringComparison.InvariantCulture)
DoSomething();
Run Code Online (Sandbox Code Playgroud)
它可以签约:
if ("something".Equals(text, StringComparison.InvariantCulture))
DoSomething();
Run Code Online (Sandbox Code Playgroud)
在C#中通常没关系.这是一种继承自C/C++ 的实践.因为在C#表达式中没有自动转换,bool所以下面的代码将无法编译:
if (Request.QueryString["PartnerID"] = null)
Run Code Online (Sandbox Code Playgroud)
然后这种做法在C#中没用(除了@IlianPinzon在评论中指出的例外),没有关于性能的信息,它只用于避免这种错误.
关于为什么是部分问题是可读性的最后一个例子,写作"something".Equals(text)就像是说"如果快乐就是那个人",而不是"如果这个人快乐".
从这些功能开始:
static bool TestRight(object value)
{ return value == null; }
static bool TestLeft(object value)
{ return null == value; }
Run Code Online (Sandbox Code Playgroud)
他们产生以下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
Run Code Online (Sandbox Code Playgroud)
唯一的区别在于行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);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果第一个操作数是null执行会稍快(因为MyType.Equals()甚至不会被调用)但这个性能增益非常小:你保存一个比较,几个跳转和一个虚函数调用.此外,你可以在相反的情况下重写函数更快(如果你真的很重要).
这里是一个小测试,MyType.Equals(object)只需返回true任何非null参数.测试将循环Int32.MaxValue次数:
Operation Total time (ms) lhs == null 10521 null == lhs 2346
似乎避免不必要调用的"优化"版本Equals()快了五倍,但请注意循环计数非常高并且实际实现Equals()为空,真正的实现将减少函数调用的相对开销(可能你会除了这种微观优化之外还有别的东西.对于系统类,您不能依赖于这些细节,例如String.Equals()将始终由运算符调用(无关紧要的顺序),但您不能假设一个代码路径更快,并且在将来的框架版本中这个事实不会改变(或针对不同的CPU架构).
不,一般来说这不是真的。比较运算符需要计算其两侧,因此将常量放在左侧没有任何好处。但是将它们放在左侧(称为尤达风格)可以减少语言中的编码错误,在这些语言中,您可以在条件中使用赋值运算符,并且您无意中将比较运算符错误地输入==为单个=:
// What you intended to write
if (a == 6) ...
// What you wrote instead
if (a = 6) ... // --> always true as the value of a is changed to 6
// What if Yoda style is used
if (6 = a) ... // --> compile time error
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1251 次 |
| 最近记录: |