13

I've just come across this code snippet in some Exchange 2010 code and I was wondering if anyone knew why the programmer has done it this way. I've never seen an If statement formatted like this. It seems so backwards there must be a good reason for it??

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

I'm assuming it might have some optimisation over the various other ways of coding the same thing;

if (MsgItem.HasAttachments) 
{
    // Code
}

or

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

Its not a big deal I'm just curious.

Thanks, Mike

UPDATE: Thanks for all the interesting points raised. Summary seems to be it's down to legacy coding standards.

Mike Mengell
  • 2,310
  • 2
  • 21
  • 35
  • possible duplicate of [== Operator and operands](http://stackoverflow.com/questions/677264/operator-and-operands) – ChrisF May 27 '10 at 14:25
  • 4
    "there must be a good reason for it" == false – Abe Miessler May 27 '10 at 14:33
  • 2
    true == because he is an idiot – fearofawhackplanet May 27 '10 at 14:33
  • Related http://stackoverflow.com/questions/2407617/confusing-if-statement/2407715#2407715 and http://stackoverflow.com/questions/1264781/in-c-difference-between-usernull-and-nulluser/1264805#1264805 – Brian Rasmussen May 27 '10 at 14:42
  • There is no good reason for it, but at least 1 bad reason. Bad reason: its weird to read. I believe (but have been known to be wrong) that any something which is a bool and written as if(something == true) or if(true == something) is optimized away to if(something) – Adam May 27 '10 at 15:42
  • @Adam: it's not *optimized* to `if (something)`, it's just that both expressions compile to identical IL. – Igby Largeman May 27 '10 at 15:56
  • By the way, with nullable bools one must compare to true in conditions. I do it all the time, with backing fields. – ANeves May 27 '10 at 17:51

8 Answers8

31

It is a left-over habit from C or C++ where you might accidentally do:

if (i = 1) {
}

This accidentally assigns 1 to i instead of doing a comparison.

Reversing the order in the check prevents this common mistake.

if (1 = i) {
}

That will not compile, and it is easy to see that you mistakenly typed = instead of ==.

This is still relevant for bools in C# because the value of an assignment is the value that was assigned.

Therefor:

if (SomeBoolVar = true) {
}

Will always be true because you are storing true into SomeBoolVar which evaluates to true. A little mistake that can be hard to track down.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 14
    People that use `if (SomeBoolVar = true)` instead of `if (SomeBoolVar)` should have their hands cut off :-) – paxdiablo May 27 '10 at 14:31
  • 1
    Haha, or at least their thumbs, so that the space bar is a pain in the butt to use. (@paxdia) – jjnguy May 27 '10 at 14:32
  • 3
    Microsoft's C# compiler will also throw up a warning if you accidentally use `=` instead of `==` in a conditional expression. – LukeH May 27 '10 at 14:36
  • @LukeH, how come in Jon Skeet's answer to this question, he says that it will compile without warnings? I don't use C# often, so I don't know myself, but I'd be stunned to know the C# compiler doesn't warn for that... every C++ compiler since the dark ages warns for that. – rmeador May 27 '10 at 15:36
  • 1
    @rmeador: I'm not sure why Jon says that -- perhaps you should ask him directly -- but the C# compiler (with default settings) definitely displays that warning. http://msdn.microsoft.com/en-us/library/c1sde1ax.aspx – LukeH May 27 '10 at 16:26
  • @LukeH I suppose it says a lot about Jon Skeet's reputation (especially on C# topics) that my first instinct was to question you and not him... he answered, btw, and you are correct. – rmeador May 27 '10 at 19:26
14

C++ and C programmers sometimes put constants first, to avoid accidentally writing

if (variable = constant)

which would perform an assignment.

In particular, explicitly for boolean comparisons, assuming HasAttachments is writable, this statement would compile and run with no warnings1, but not have the intended behaviour in C#:

if (MsgItem.HasAttachments = true)

For non-Boolean expressions, this isn't usually an issue in C# because the condition of an if statement has to be implicitly convertible to bool... and for Boolean expressions, your middle form is preferred anyway:

if (MsgItem.HasAttachments)

I would be amazed if it had any performance impact at all - and probably no impact on the generated IL to start with.


1 Oops - the MS C# compiler does indeed warn for this:

warning CS0665: Assignment in conditional expression is always constant; did you mean to use == instead of = ?

I haven't tried it under Mono though; that may or may not give a warning. It's certainly valid C# code.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Believe it or not, it does translate to *slightly* different IL. See jeffmaphone's answer to [a very similar question I posted a long time ago](http://stackoverflow.com/questions/1070063/does-if-bool-true-require-one-more-step-than-if-bool). – Dan Tao May 27 '10 at 14:28
  • @Dan: jeffmaphone's answer is using C++, not C#. In C# they will compile to exactly the same IL. – LukeH May 27 '10 at 14:44
  • @LukeH: Ha, thanks for reminding me (should've re-read the answer before linking to it -- neglected to realize this question is C#-specific while mine was language agnostic). And I notice you're the one who pointed out this very fact in said question! – Dan Tao May 27 '10 at 15:05
  • why do you say it will compile without warnings? It stands to reason that the compiler would be smart enough to warn for that, and LukeH says as much in a comment on Justin Nelson - jjnguy's answer, which has been upvoted... – rmeador May 27 '10 at 17:30
  • @rmeador: I thought it would be without warnings, but fortunately the compiler *does* warn on this. Will edit. – Jon Skeet May 27 '10 at 17:34
11

These are called "Yoda Conditions" - the original idea is that if you accidentally type a single =, the compilation will fail because the constant value is on the left hand side.

Community
  • 1
  • 1
Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
6

Because the programmer is an clown :-) The whole point of boolean conditions is that you name them such that they make sense as booleans:

if (MsgItem.HasAttachments)

and this clearly does so I don't know why the coder shot themselves in the foot by testing for equality against true.

Because, in all seriousness, true == MsgItem.HasAttachments is just another boolean, so where do you stop?

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

And so on, ad infinitum.

The whole trick of using the constant first to avoid the problem of accidentally using = assignment instead of == equality shouldn't be an issue here since you shouldn't be checking a boolean against either true or false. You should be using one of:

if (cond)
if (!cond)
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
3

There's a perfectly fine reason to write if (true == myvar): the variable (or expression) might not be a boolean expression - it might be a bool?. The expression then would be equivalent to if(myvar ?? false) - and I prefer this second syntax since it's immediately obvious that you're dealing with a nullable value. It's technically possible a custom == operator is being used (potentially in combination with an implicit type-conversion), but that's quite unlikely as doing something like that is generally frowned upon and isn't practical or handy either.

Placing the constant first, as many others have pointed out, may reduce accidental errors - personally, I don't think those errors occur often enough to matter, but it can't harm.

Most likely, however, the original author was just a bit confused the moment he wrote that code.

Eamon Nerbonne
  • 47,023
  • 20
  • 101
  • 166
2

Under mono, they all generate the same IL (ldloc.0; brfalse <LOC>):

Source:

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

Personally, it drive me nuts when people do if (SomePredicate() == true). Unless it's actually returning an object with an overloaded == operator, the comparison against true is completely unnecessary. Why stop at one comparison?

// make extra sure SomePredicate returns true
if ((SomePredicate() == true) == true) 
{
     // ...
} 
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
1

maybe the == operator has been overloaded and MsgItem.HasAttachments has more information then just a bool? I don't know. Just an idea.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
Kenneth J
  • 4,846
  • 11
  • 39
  • 56
  • 1
    Ah the old "Daily WTF" {true,false,maybe} type :-) – paxdiablo May 27 '10 at 14:33
  • 1
    Nope, if you overload equality operators things are not always what they seem. If you have 'true == MsgItem.HasAttachments' it will run the == operator for the bool class and pass MsgItem.HasAttachments into the operator implementation. If you have it the other way round it will run the == operator implemantation on the type of HasAttachments and pass 'true' into it. Clearly the behaviour does not have to be the same. So at least when overloading operators the order often does make a difference. – Cobusve May 27 '10 at 15:14
0

This is common requirement when writing mission critical code. It is there to prevent accidental assignment when you meant to do a check. In a language like C# the compiler will warn you about it, so it's not as necessary, but it is a left over habit for many programmers.

Stephan
  • 5,430
  • 2
  • 23
  • 31