0

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; }
}
whymatter
  • 755
  • 8
  • 18
  • It's because `Equals` checks for the type too, since they are different the output is different – chiapa Jul 07 '15 at 16:17
  • Why are they different? I CheckDispo is bool and true is bool too? – whymatter Jul 07 '15 at 16:22
  • I'm not sure but I guess `Equals` checks for object equality, while the `==` checks for the values equality – chiapa Jul 07 '15 at 16:34
  • 1
    possible duplicate of [C# difference between \`==\` and .Equals()](http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) – psoshmo Jul 07 '15 at 16:42
  • 1
    Okay but maybe you can have a look at my question.. I am comparing bool! This is a value Type. When i instantiate Item and call equals on CheckDispo then everything works... – whymatter Jul 07 '15 at 17:04
  • @ragerory This isn't java `bool` is just an alias for `Boolean` and `Boolean` is a value type. – juharr Jul 07 '15 at 17:06
  • 3
    `Boolean` and `bool` are **not** different. You are confusing Java and C#. In C#, `bool` is just an alias for `System.Boolean`, which is a struct, not a class. – Dennis_E Jul 07 '15 at 17:07
  • Ugh. I've been going back and forth too much. You guys are right. My mind was in Java. – ragerory Jul 07 '15 at 17:09
  • 1
    @psoshmo In that question it's comparing an `object` to a `string`. Here the types are both `bool`. – juharr Jul 07 '15 at 17:12

2 Answers2

2

Both results should return true. I have tested your same scenario above and it does return true in both cases. Please see below screenshot.

enter image description here

The boolean class overrides the Equals method as follows:

 public override bool Equals(object obj)
        {
            if (!(obj as bool))
            {
                return false;
            }
            return this == (bool)obj;
        }

It also provides a separate overloaded method which accepts a boolean as a parameter. This just uses the equality operator. I think this was added because it provides better performance over the Equals method because it avoids the typecasting overhead.

public bool Equals(bool obj)
        {
            return this == obj;
        }

In your case since you are passing a boolean it should hit the above overloaded method and as you can see, it is just using the === operator.

Joseph Caruana
  • 2,241
  • 3
  • 31
  • 48
  • I would suggest that you try the above code in a simple Console application to check what results you receive. When I encounter similar strange behaviours, I usually try to extract things as a separate simplified project because it is easier to troubleshoot and debug. – Joseph Caruana Jul 07 '15 at 17:14
  • 1
    @ ragerory. I am casting to make sure that the result is of type 'bit' to mimic the question's scenario – Joseph Caruana Jul 07 '15 at 17:15
  • 1
    Okey your right, the bool in our company is representated by smallint -1, when im casting the -1 to bit the equal works, if i dont do that AutoMapper sets CheckDispo to true but the equal dont work, i dont know why... Casting will solve my Problem THANKS!! – whymatter Jul 07 '15 at 17:29
0

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.

whymatter
  • 755
  • 8
  • 18