Julian Gold
Julian Gold

Reputation: 1286

Arithmetic comparison of objects in C#

I have two object instances which could be integers or doubles. I want to find out which is the smaller:

int ix = 1;
int iy = 2;
object ox = ix;
object oy = iy;
if (ox < oy) // This is an error
{
...
}

Is it possible to perform this comparison without hideously inefficient-looking

if (ox.GetType() == typeof(int))
{
}
else if (ox.GetType() == typeof(double))
{
}

tests?

Upvotes: 0

Views: 89

Answers (3)

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391396

If you "know" that the types can be compared, but:

  1. You don't know the exact type (without reflection)
  2. You don't know if they're even the same type

Then the way to do this is by using dynamic:

void Main()
{
    int ix = 1;
    int iy = 2;
    dynamic ox = ix;
    dynamic oy = iy;

    if (ox < oy)
        Debug.WriteLine("ox < oy");
    else if (ox == oy)
        Debug.WriteLine("ox == oy");
    else
        Debug.WriteLine("ox > oy");
}

Please note that dynamic is like an object in many cases, but will defer until runtime the exact binding and handling. This means that the above code would throw an exception at runtime if ox and/or oy happen to be types that doesn't know how to be compared.

Upvotes: 1

Dennis_E
Dennis_E

Reputation: 8894

Convert.ToDouble(ox).CompareTo(Convert.ToDouble(oy));

This will of course throw an InvalidCastException if one of them is not a number.

Upvotes: 0

xanatos
xanatos

Reputation: 111870

There is an interface, IComparable, for that

Defines a generalized type-specific comparison method that a value type or class implements to order or sort its instances.

and

All numeric types (such as Int32 and Double) implement IComparable, as do String, Char, and DateTime. Custom types should also provide their own implementation of IComparable to enable object instances to be ordered or sorted.

You could write...

int ix = 1;
int iy = 2;
object ox = ix;
object oy = iy;

IComparable cx = ox as IComparable;

// Does our type supports comparison?
if (cx == null && ox != null)
{
    throw new NotSupportedException();
}

if ((cx != null && cx.CompareTo(oy) < 0) || (ox == null && oy != null)) // x < y
{

}

Note the special case handling for ox == null

Mmmh... shorter..

int cmp = System.Collections.Comparer.Default.Compare(ox, oy);

if (cmp < 0) {
}

It seems that the System.Collections.Comparer does everything necessary (using the IComparable interface)

You can even use

int cmp = System.Collections.Generic.Comparer<object>.Default.Compare(ox, oy);

The object type doesn't support the IComparable<object>, so the IComparer interface will be used (in truth, in the .NET 4.5 implementation, the Comparer<object>.Default will use the Comparer.Default of the previous example :-) )

IMPORTANT: in all these cases, ox and oy MUST be of the same type (or null). You CAN'T mix int and double.

Upvotes: 4

Related Questions