whymatter whymatter - 3 months ago 21
C# Question

.Net, C# - Boolean.Equal differs from == compare

We are using AutoMapper to map from IDataReader to List of Entities.

One Problem that i noticed while unit testing was the following. If we read an bool value from database (bit), AutoMapper does verry fine. But when we us FluentAssertions for UnitTesting there is a problem with the ShouldAllBeEquivalentTo function. It says True expected but True returned on the bool property of the entity.

So i tried to check the bool properties and noticed that

expected == returnd
works (returns
true
) but
expected.Equals(returned)
does not work (returns
false
)?!

I thought
==
and
equals
should be almost the same for bool type?

What could cause this strange behaviour?

Here some code:

using (var connection = new SqlConnection("server=someServer;user id=someUser;password=***;database=someDatabase;MultipleActiveResultSets=True"))
using (var command = connection.CreateCommand())
{
connection.Open();

var itemsBefore = new List<Item> { new Item { CheckDispo = true } };

command.CommandText = "SELECT CheckDispo FROM Items WHERE ItemId = 1814";
var itemsAfter = Mapper.DynamicMap<List<Item>>(command.ExecuteReader());

var a = itemsAfter[0].CheckDispo.Equals(true); // false
var b = itemsAfter[0].CheckDispo == true; // true
}

public class Item
{
public bool CheckDispo { get; set; }
}

Answer

Sorry for this late edit, but I have found what has gone wrong. We read the property out of our database and our 'boolean' is represented by -1 not 1. Automapper uses dynamically generated IL code to read from a datareader and because they do this, automapper is able to write -1 to the bool field. This results in a value of 0xff in out RAM. If we now look at the il code for the equals method then we understand wy .equal is not ==.

.method public hidebysig newslot virtual final 
        instance bool  Equals(bool obj) cil managed
{
  .custom instance void __DynamicallyInvokableAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       6 (0x6)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldind.u1
  IL_0002:  ldarg.1
  IL_0003:  ceq
  IL_0005:  ret
} // end of method Boolean::Equals

This loads an 1 and our value to the stack and compares both. Due to the fact that in our RAM the bool is -1 (0xFF) the comparison will return false.

See also this item on github.com for more information.

Comments