Search

Boolean comparison in .NET by Charles Perreault

Closed
as Won't Fix Help for as Won't Fix

4
Sign in to vote
0
Sign in to vote
Sign in
to vote
Type: Bug
ID: 455553
Opened: 5/21/2009 10:08:59 AM
Access Restriction: Public
0
Workaround(s)
0
User(s) can reproduce this bug
Sometimes, true != true. Let me explain. I'm from C++ where false is 0, and true is everything but 0. Since C# has a strongly typed Boolean type, I thought that the == and != operators were correctly implemented: that true == true whatever the byte value behind true was (except 0). This is not the case, and is not clearly documented. Boolean.Equals is not overridden, therefore the comparison is left to Object.Equals that compares the byte value. Even the CompareTo method won't return 0. In my opinion that is incorrect. Booleans should be bits, 0 or 1, and comparable as such. I shouldn't have to write "!bool1 == !bool2" or an helper method like in C++ to compare booleans, not in 2008.

My problem started when writing unit tests with PEX. Sometimes, PEX will use boolean values other than true (0x01) and false (0x00), like true (0x02 or 0x80). While those values are indeed true, I encountered a lot of problems when creating assertions for comparing expected booleans.

It uses the following method because that cast is safe in MSIL, but not allowed by the C# compiler:
public static unsafe bool ByteToBoolean(byte b)
{
    return *(((bool*) &b));
}

Those assertions will work if boolParameter is true/false, but will fail if it is (bool)0x02:
PexAssert.AreEqual(boolParameter, boolResult);
PexAssert.IsTrue(boolParameter == boolResult);
Details (expand)
Product Language
English

Version

.NET Framework 3.5 SP1
Operating System
Windows XP Professional
Operating System Language
English
Steps to Reproduce
bool true1 = true;
bool true2 = PexSafeHelper.ByteToBoolean((byte)0x02);

bool compare = (true1 == true2) => false
Boolean.AreEquals(true1, true2) => false
true1.CompareTo(true2) => 1

In the VS2008 debugger, the watch for the expression "true1 == true2" returns TRUE, while "compare" will evaluate to FALSE. The debugger is lying !
Actual Results
1- Visual Studio 2008 compares boolean with the == operator as logically expected, but not as the .NET language actually does. This is confusing.

2- Boolean comparison does not work correctly when the boolean value is 0x02.
Expected Results
1- Visual Studio 2008 debugger should evaluate the == operator like the .NET languages does.

2- Boolean comparison should produce the same result as the following method, which is safe for true values other than 0x01:
bool Boolean.Equals(bool b1, bool b2)
{
return !b1 == !b2;
}

TAP Code (if applicable)
 
      You can indicate your satisfaction with how Microsoft handled this issue by completing this quick 3 question survey. [Details]

 

File Attachments
0 attachments
Sign in to post a comment.
Posted by Charles Perreault on 5/21/2009 at 10:35 AM
GetHashCode() works OK, it returns 1 for both true1 and true2.
Really, sanitizing boolean parameters would be annoying:
if(boolParameter)
{
boolParameter = true;
}

A lot of legacy code uses the redundant boolean comparison in their if statements:
if (boolParameter == true)
{
...
}

which would fail if boolParameter = (bool)0x02 or PexSafeHelper.ByteToBoolean((byte)0x02). I don't say the above code is optimal, but it should work...
Posted by Charles Perreault on 5/21/2009 at 10:44 AM
Also, !!true2 does not work: it returns true2 (0x02) instead of true. In C++ this would work.

The compiler seems to optimize the request and ignore the double negation, even in DEBUG.
Posted by Microsoft on 5/22/2009 at 4:14 AM
Thank you for your feedback, We are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Posted by Microsoft on 5/23/2009 at 3:08 AM
Thanks for your feedback.

We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution.
These specialized experts will follow-up with your issue.
Posted by Microsoft on 6/12/2009 at 2:15 PM
Hi Charles,

Thanks for taking the time to report this bug. Yes, Boolean values are represented as bytes, and yes, this representation can leak through if you are using non-standard values for true and false. Both the C# Compiler team and the CLR team have looked at this bug, and our current resolution is that we won't fix it. There is a lot of risk involved in changing something as low in the system as Boolean, because so many things depend on the type and it's entirely possible someone took a dependency on this behavior. Non-standard Booleans are such a corner case that we can't justify taking that risk. The assumption is that anyone who does somehow manage to create one of these understands the implications.

Thanks,
Melitta
Base Class Libraries Team