简体   繁体   中英

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?

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 .

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.

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

如果其中之一不是数字,这当然会引发InvalidCastException

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM