C#if语句。内部运作问题

时间:2010-05-27 14:19:13

标签: c#

我刚刚在一些Exchange 2010代码中看到了这段代码,我想知道是否有人知道程序员为什么这样做了。我从未见过像这样格式化的If语句。看起来如此倒退必定有一个很好的理由吗?

if (true == MsgItem.HasAttachments)
{
    // Code
}

我假设它可能会对编码相同内容的各种其他方式进行一些优化;

if (MsgItem.HasAttachments) 
{
    // Code
}

if (MsgItem.HasAttachments == true)
{
    // Code
}

这不是什么大问题,我只是好奇。

谢谢, 麦克

更新:感谢所有有趣的观点。摘要似乎归结为传统编码标准。

8 个答案:

答案 0 :(得分:31)

这是C或C ++的遗留习惯,你可能不小心做了:

if (i = 1) {
}

这意外地将1分配给i而不是进行比较。

撤销支票中的顺序可以防止出现这种常见错误。

if (1 = i) {
}

这将无法编译,很容易看到您错误地输入=而不是==

这仍然与C#中的bools相关,因为赋值的值是指定的值。

为此:

if (SomeBoolVar = true) {
}

永远都是如此,因为您将true存储到评估为SomeBoolVar的{​​{1}}中。一个可能难以追查的小错误。

答案 1 :(得分:14)

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

if (variable = constant)

将执行任务。

特别是,显式地用于布尔比较,假设HasAttachments是可写的,这个语句将编译并运行而没有警告 1 ,但在C#中没有预期的行为:

if (MsgItem.HasAttachments = true)

对于非布尔表达式,这通常不是C#中的问题,因为if语句的条件必须可隐式转换为bool ...而对于布尔表达式,您的中间无论如何,表格是首选:

if (MsgItem.HasAttachments)

如果它完全具有任何性能影响,我会感到惊讶 - 并且可能对生成的IL没有任何影响。


1 糟糕 - MS C#编译器确实警告过:

  

警告CS0665:条件表达式中的赋值始终是常量;你的意思是使用==而不是=?

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

答案 2 :(得分:11)

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

答案 3 :(得分:6)

因为程序员是一个小丑:-)布尔条件的全部意义在于你将它们命名为使得 sense 为布尔值:

if (MsgItem.HasAttachments)

这显然是这样的,我不知道为什么编码员通过测试对true的平等来自责。

因为,严肃地说,true == MsgItem.HasAttachments只是另一个布尔值,所以你在哪里停止?

if (true == MsgItem.HasAttachments)
if (true == (true == MsgItem.HasAttachments))
if (true == (true == (true == MsgItem.HasAttachments)))
: : :

依此类推,无限无休。

首先使用常量来避免意外使用=赋值而不是==相等的问题应该不是问题,因为你不应该检查一个布尔值truefalse。你应该使用以下之一:

if (cond)
if (!cond)

答案 4 :(得分:3)

if (true == myvar)有一个很好的理由:变量(或表达式)可能是布尔表达式 - 它可能是bool?。那么表达式将等同于if(myvar ?? false) - 我更喜欢第二种语法,因为很明显你正在处理一个可以为空的值。技术上可能正在使用自定义==运算符(可能与隐式类型转换相结合),但这样做的可能性很小,因为这样做通常不赞成,也不实用或不方便。

正如许多其他人所指出的那样,放置常数可以减少意外错误 - 就个人而言,我认为这些错误不会经常发生,但它不会造成伤害。

然而,最有可能的是,原作者在编写该代码时只是有点困惑。

答案 5 :(得分:2)

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

来源:

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:

// 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...

就个人而言,当人们if (SomePredicate() == true)时,它会让我感到疯狂。除非它实际上返回一个带有重载==运算符的对象,否则完全不需要与true进行比较。为什么停止比较?

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

答案 6 :(得分:1)

可能==运算符已超载且MsgItem.HasAttachments有更多信息,只有bool?我不知道。只是一个想法。

答案 7 :(得分:0)

这是编写关键任务代码时的常见要求。当您打算进行检查时,它可以防止意外分配。在像C#这样的语言中,编译器会警告你它,所以它不是必要的,但对许多程序员来说这是一个遗留下来的习惯。