Implicit (bool) and == operator override - handle if statements correctly

c#, implicit, operators, overriding

Solution

I think you've written too much code :-)

The following is sufficient:

public class Foo
{
    public bool Result { get; set; }

    public static implicit operator bool(Foo foo)
    {
        return !object.ReferenceEquals(foo, null) && foo.Result;
    }
}

The compiler will then know how to implicitly convert variables of type `Foo` into `bool`. (And `null` will be converted to `false`).

So, when you write:

new Foo() == false

The compiler will use the implicit type converter to get a `bool` value from `Foo` and then use the standard equality operator for `bool`.

If we look at the IL that the compiler generates for that expression we find:

newobj instance void FooBool.Foo::.ctor()               // new Foo()
call bool FooBool.Foo::op_Implicit(class FooBool.Foo)   // implicit operator (Foo => bool)
ldc.i4.0                                                // false
ceq                                                     // equality operator (bool)

Here's a test:

static void Main(string[] args)
{
    AssertTrue(new Foo() == false);
    AssertTrue(false == new Foo());
    AssertFalse(new Foo() != false);
    AssertFalse(false != new Foo());
    AssertTrue(new Foo { Result = true } == true);
    AssertTrue(true == new Foo { Result = true });
    AssertFalse(new Foo { Result = true } != true);
    AssertFalse(true != new Foo { Result = true });
}

static void AssertTrue(bool value)
{
    Console.WriteLine(value ? "ok" : "not ok");
}

static void AssertFalse(bool value)
{
    Console.WriteLine(value ? "not ok" : "ok");
}

It prints `ok` for each test. So this simplified code should fulfill your needs if I understood them correctly.

UPDATE

To allow the equality operator to work for instances of `Foo` (which may be null):

public static bool operator ==(Foo a, Foo b)
{
    if (object.ReferenceEquals(a, b))
    {
        return true;
    }
    else if (object.ReferenceEquals(a, null))
    {
        return !b.Result;
    }
    else if (object.ReferenceEquals(b, null))
    {
        return !a.Result;
    }
    else
    {
        return a.Result == b.Result;
    }
}

You should then also implement the inequality operator:

public static bool operator !=(Foo a, Foo b)
{
    return !(a == b);
}

And also override `GetHashCode` + `Equals`

public override int GetHashCode()
{
    return this.Result ? 1 : 0;
}

public override bool Equals(object obj)
{
    if (object.ReferenceEquals(obj, null))
    {
        return !this.Result;
    }

    Type t = obj.GetType();

    if (t == typeof(Foo))
    {
        return this.Result == ((Foo)obj).Result;
    }
    else if (t == typeof(bool))
    {
        return this.Result == (bool)obj;
    }
    else
    {
        return false;
    }
}

Problem

I have a custom class with implement both the `==` and the `implicit` for boolean operator. Is this the correct way to handle all possible, if ==/!= statements and get the expected result? Like this: ``` public class Foo { public bool Result { get; set; } public static bool operator ==(bool @bool, Foo foo) { return Equals(foo, @bool); } public static bool operator !=(bool @bool, Foo foo) { return NotEquals(foo, @bool); } public static bool operator ==(Foo foo, bool @bool) { return Equals(foo, @bool); } public static bool operator !=(Foo foo, bool @bool) { return NotEquals(foo, @bool); } public static bool operator ==(Foo foo, Foo fooB) { return Equals(foo, fooB); } public static bool operator !=(Foo foo, Foo fooB) { return NotEquals(foo, fooB); } public static implicit operator bool(Foo foo) { try { return foo.Result; } catch { return false; } } private static bool Equals(Foo foo, Foo fooB) { if (object.Equals(foo, null)) { if (object.Equals(fooB, null)) return true; return false; } if (object.Equals(fooB, null)) return false; return foo.Result == fooB.Result; } private static bool NotEquals(Foo foo, Foo fooB) { if (object.Equals(foo, null)) { if (object.Equals(fooB, null)) return false; return true; } if (object.Equals(fooB, null)) return true; return fooB.Result != foo.Result; } private static bool Equals(Foo foo, bool @bool) { if (object.Equals(foo, null)) return true; return @bool == foo.Result; } private static bool NotEquals(Foo foo, bool @bool) { if (object.Equals(foo, null)) return false; return @bool != foo.Result; } } ``` I am especially wondering about the fact that its seems you really need to implement overloads for either ``` if (new Foo() != true) ``` and ``` if (true != new Foo()) ```

Original source