Использование CompareTo() для разных типов .NET (например, int или double)

У меня есть статический метод, который принимает две переменные типа объекта и запускает метод CompareTo():

public static int Compare(Object objA, Object objB)
{
   return (((IComparable)objA).CompareTo(objB));
}

Проблема в том, что CompareTo() выдает исключение при попытке сравнить разные типы (например, int и double). Кто-нибудь знает лучший способ в С# для сравнения двух разных типов? Или обходной путь к этой проблеме?

Спасибо


person Yossin    schedule 08.03.2010    source источник


Ответы (5)


В C# нет общего способа решить эту проблему, потому что для нее нет общего решения. Если потери информации нет, компилятор C# будет неявно преобразовывать один тип в другой, а затем сравнивать их. В любом другом случае это вызовет исключение.

В этом примере программист, реализовавший IComplarable Интерфейс отвечает за принятие решения о том, сравнимы ли два объекта, и вы, как пользователь класса, не имеете на это никакого влияния.

person Nenad Dobrilovic    schedule 08.03.2010

Возможный обходной путь — использовать интерфейс IComparable<T> через отражение:

public static int Compare(Object objA, Object objB)
{
    Type comparableType = typeof(IComparable<>).MakeGenericType(objA.GetType());
    MethodInfo compareMethod = comparableType.GetMethod("CompareTo");
    return (int)compareMethod.Invoke(objA, new[] { objB });
}

Однако это будет медленнее и будет работать только в том случае, если тип objB можно преобразовать в тип objA.

person Thomas Levesque    schedule 08.03.2010

Если вы работаете только с числовыми значениями, вы можете найти обходной путь для решения проблемы, описанной Ненадом, используя это:

public static int Compare(Object objA, Object objB)
{
    object objB_as_AType = System.Convert.ChangeType(objB, objA.GetType());
    return (((IComparable)objA).CompareTo(objB_as_AType));
}

Но будьте очень осторожны, потому что вы предполагаете, что A является IComparable без какой-либо проверки, и вам нужно будет гарантировать, что задействованные типы действительно имеют преобразования друг в друга.

person Seb    schedule 08.03.2010

Для этого вам нужно построить свою собственную логику, в основном потому, что только вы знаете, что должно делать основное сравнение.

например, взяв ваш пример, сравнивая

int i = 10;
double d = 10.2;

эти равны? Должно ли целое число быть повышено до двойного, а затем сравниваться? Тогда нет, не равно.
Должен ли double усекаться до целого числа? Тогда да, они равны.

В вашем статическом методе вам нужно проверить, совпадают ли типы A и B, если да, то вы можете вызвать a.compareTo(b).

Если нет, то вам нужно решить, как вы хотите сравнивать разные типы, и реализовать это решение в своем статическом методе.

Надеюсь это поможет

person Binary Worrier    schedule 08.03.2010

Если вы сравниваете только числа, это будет работать в большинстве случаев:

public static int Compare(Object objA, Object objB) 
{ 
   return (((IComparable)Convert.ToDouble(objA)).CompareTo(Convert.ToDouble(objB))); 
} 
person Gabe    schedule 08.03.2010