Chillersanim
Chillersanim

Reputation: 465

C#, multiple == operator overloads without ambiguous null check

Introduction:
I have a few classes which do the same work, but with different value types (e.g. Vectors of floats or integers).
Now I want to be able to check for equality, this equality should also work in between the types (such as vectorF == vectorI).
Also, it should be possible to do a null check (vectorF == null).

Approach:
My approach is to create multiple overloads for the == and != operators, one for each possible combination.

public sealed class VectorF
{
    [...]

    public static bool operator == (VectorF left, VectorI right)
    {
        // Implementation...
    }

    public static bool operator == (VectorF left, VectorF right)
    {
        // Implementation...
    }

    // Same for != operator
    [...]
}

Problem:
Using multiple overloads, I cannot just do a null check with the == operator, as the call would be ambiguous.

var v = new VectorF([...]);

if (v == null)    // This call is ambiguous
[...]

I'm aware of the possibility to use a ReferenceEquals or null casting instead, but that approachis a serious restriction for me.

var v = new VectorF([...]);

if(object.ReferenceEquals(v, null))    // Would work, is not user friendly.
[...]

if(v == (VectorF)null)    // Would also work, is neither user friendly.
[...]

Question:
Is there a way to implement the == operator in a way, that it allows the simple null check, and allows for equality check between the different vectors?

Alternatively, is there another way how I could/should implement this?

Upvotes: 18

Views: 2671

Answers (3)

InBetween
InBetween

Reputation: 32750

I'd push back on the whole design to begin with. I would never implement == with value semantics between different types, I'd find it rather confusing: instaceTypedA == instanceTypedB yells reference equality (at least to me).

If you need this to work, then implement an implicit conversion between VectorI and VectorF. This is how the framework works. When you do the following:

int i = 1;
double d = 1;
var b = i == d;

An oveload ==(int, double) isn't magically produced. What happens is that i is implicitly converted to double and ==(double, double) is invoked.

Upvotes: 20

Paolo Tedesco
Paolo Tedesco

Reputation: 57202

What I would do in this case it not to overload the == operator, and instead do something like:

public static bool operator == (VectorF left, object right) {
    if (object.ReferenceEquals(null, right)) {
        // handle null case
    }
    VectorF rightF = right as VectorF;
    if (!object.ReferenceEquals(null, rightF)) {
        // Compare VectorF
    }
    VectorI rightI = right as VectorI;
    if (!object.ReferenceEquals(null, rightI)) {
        // Compare VectorI
    }
    // and so on...
}

Upvotes: 3

Patrick Hofman
Patrick Hofman

Reputation: 156978

You can turn around the comparison by using is:

if (v is VectorF)

This check will fail if v is null.

Upvotes: 7

Related Questions