C#if语句。内部加工

C#if语句。内部加工,c#,C#,我刚刚在一些Exchange2010代码中遇到了这个代码片段,我想知道是否有人知道程序员为什么这样做。我从未见过这样格式的If语句。看起来很落后,一定有很好的理由吧 if (true == MsgItem.HasAttachments) { // Code } 我假设它可能比其他各种编码相同东西的方法有一些优化 if (MsgItem.HasAttachments) { // Code } 或 没什么大不了的,我只是好奇而已 谢谢, 迈克 更新:感谢您提出的所有有趣的观点。

我刚刚在一些Exchange2010代码中遇到了这个代码片段,我想知道是否有人知道程序员为什么这样做。我从未见过这样格式的If语句。看起来很落后,一定有很好的理由吧

if (true == MsgItem.HasAttachments)
{
    // Code
}
我假设它可能比其他各种编码相同东西的方法有一些优化

if (MsgItem.HasAttachments) 
{
    // Code
}

没什么大不了的,我只是好奇而已

谢谢, 迈克


更新:感谢您提出的所有有趣的观点。总结似乎是由于传统的编码标准。

这些被称为“”-最初的想法是,如果您意外地键入单个
=
,编译将失败,因为常量值位于左侧

> P>是C或C++的遗留习惯,在这里你可能意外地做:

if (i = 1) {
}
这会意外地将
1
分配给
i
,而不是进行比较

在检查中颠倒顺序可以防止这种常见错误

if (1 = i) {
}
这将无法编译,很容易看出您错误地键入了
=
,而不是
=

这仍然与C#中的
bools
有关,因为赋值的值就是已赋值的值

因此:

if (SomeBoolVar = true) {
}

将始终为true,因为您正在将
true
存储到
SomeBoolVar
中,其计算结果为
true
。一个很难找到的小错误。

C++和C程序员有时会将常量放在第一位,以避免意外写入

if (variable = constant)
它将执行一项任务

特别是,对于布尔比较,假设
hasaAttachments
是可写的,则此语句将编译并运行,而不会出现警告1,但在C#中没有预期的行为:

对于非布尔表达式,这在C中通常不是问题,因为
if
语句的条件必须隐式转换为
bool
。。。对于布尔表达式,您还是首选中间形式:

if (MsgItem.HasAttachments)
如果它对性能有任何影响的话,我会感到惊讶——而且可能对生成的IL没有影响


1 Oops-MS C#编译器确实对此发出警告:

警告CS0665:条件表达式中的赋值始终为常量;你的意思是用==代替=


我还没有在Mono下尝试过;可能会也可能不会发出警告。它当然是有效的C代码。

可能是
=
操作符被重载了,并且
MsgItem。HasAttachments
比一个
bool
有更多信息?我不知道。这只是一个想法。

这是编写任务关键型代码时的常见要求。当你打算做一次检查时,它是用来防止意外分配的。在C#这样的语言中,编译器会警告您,因此这不是必要的,但这是许多程序员的一个遗留习惯。

因为程序员是一个小丑:-)布尔条件的全部要点是您将它们命名为布尔条件,以便它们可以理解为布尔:

if (MsgItem.HasAttachments)
这很明显是这样的,我不知道为什么编码员通过测试
true
的相等性来击中自己的脚

因为,非常严肃地说,
true==MsgItem.hasaAttachments
只是另一个布尔值,所以您应该停在哪里

if (true == MsgItem.HasAttachments)
if (true == (true == MsgItem.HasAttachments))
if (true == (true == (true == MsgItem.HasAttachments)))
: : :
诸如此类,无穷无尽

首先使用常量以避免意外使用
=
赋值而不是
=
相等的问题的整个技巧在这里不应该是一个问题,因为您不应该根据
true
false
检查布尔值。您应该使用以下选项之一:

if (cond)
if (!cond)

在mono下,它们都生成相同的IL(
ldloc.0;brfalse
):

资料来源:

using System;
class Foo
{
    static void Main()
    {
        bool bar = Console.ReadLine() == "bar";
        if (bar)
        {
            Console.WriteLine("bar");
        }

        if (true == bar)
        {
            Console.WriteLine("true == bar");
        }

        if (bar == true)
        {
            Console.WriteLine("bar == true");
        }
    }
}
IL:


就我个人而言,如果(SomePredicate()==true)有人这样做,我会发疯。除非它实际返回的对象带有重载的
=
运算符,否则与
true
的比较完全没有必要。为什么只进行一次比较

// make extra sure SomePredicate returns true
if ((SomePredicate() == true) == true) 
{
     // ...
} 

如果(true==myvar),那么编写
有一个很好的理由:变量(或表达式)可能不是布尔表达式-它可能是
bool?
。然后表达式将相当于
if(myvar??false)
——我更喜欢第二种语法,因为很明显,您处理的是一个可为null的值。从技术上讲,可以使用自定义的
==
运算符(可能与隐式类型转换结合使用),但这不太可能,因为这样做通常不受欢迎,也不实用或不方便

正如许多其他人指出的那样,将常数放在第一位可能会减少意外错误——就我个人而言,我认为这些错误发生的频率不足以产生影响,但不会造成伤害


然而,最有可能的是,原作者在编写代码的那一刻有点困惑。

可能重复“必须有一个好的理由”==FalseTreal==因为他是一个白痴,没有好的理由,但至少有一个坏的理由。不好的理由:读起来很奇怪。我相信(但被认为是错误的)任何一个bool的东西,写得好像(something==true)或者如果(true==something)被优化了,如果(something)信不信由你,它会转换成稍微不同的IL。请看杰弗曼的回答。丹:杰弗曼的答案是用C++,而不是C。在C#中,他们将编译成完全相同的IL。@LukeH:Ha,谢谢你提醒我(在链接之前应该重新阅读答案——忽略了这个问题是C#特定的,而我的问题是语言不可知的)。我注意到你是在上述问题中指出这一事实的人!为什么你说它会在没有警告的情况下编译?毫无疑问,编译器会足够聪明地发出警告,LukeH在一篇文章中也这么说
using System;
class Foo
{
    static void Main()
    {
        bool bar = Console.ReadLine() == "bar";
        if (bar)
        {
            Console.WriteLine("bar");
        }

        if (true == bar)
        {
            Console.WriteLine("true == bar");
        }

        if (bar == true)
        {
            Console.WriteLine("bar == true");
        }
    }
}
// snip...
IL_000a:  call bool string::op_Equality(string, string)
IL_000f:  stloc.0 
IL_0010:  ldloc.0 
IL_0011:  brfalse IL_0020

IL_0016:  ldstr "bar"
IL_001b:  call void class [mscorlib]System.Console::WriteLine(string)
IL_0020:  ldloc.0 
IL_0021:  brfalse IL_0030

IL_0026:  ldstr "true == bar"
IL_002b:  call void class [mscorlib]System.Console::WriteLine(string)
IL_0030:  ldloc.0 
IL_0031:  brfalse IL_0040
// snip...
// make extra sure SomePredicate returns true
if ((SomePredicate() == true) == true) 
{
     // ...
}