Как я могу использовать операторы сравнения с коробочными числами неизвестных типов в C#?

Я хочу создать функции, которые сравнивают значения двух объектов и ведут себя идентично встроенным операторам сравнения. Я не могу знать типы объектов во время компиляции и имею доступ только к ним как к объектам. Любое решение, основанное на приведении их к базовым типам или изменении функции на обобщенную, не поможет по этим причинам.

Моя наивная первая реализация была бы что-то вроде:

bool LessThan(object left, object right) {
    return left < right;
}

но к сожалению это приводит к ошибке

error CS0019: Operator `<' cannot be applied to operands of type `object' and `object'

Затем я попытался использовать выражения LINQ

bool LessThan(object left, object right) {
    BinaryExpression expression = Expression.Equal(Expression.Constant(left), Expression.Constant(right));
    return (bool) Expression.Lambda(expression).Compile().DynamicInvoke());
}

который работает, когда два объекта имеют одинаковый тип, но вы получаете сообщение об ошибке, как

System.InvalidOperationException : The binary operator LessThan is not defined for the types 'System.Single' and 'System.Double'.

когда объекты имеют разные типы.

Можно ли конвертировать их в двойники, а затем провести сравнение?

bool LessThan(object left, object right) {
    return ((double) Convert.ChangeType(left, typeof(double))
         < ((double) Convert.ChangeType(right, typeof(double));
}

Это, кажется, дает желаемое поведение, но я подозреваю, что преобразования в некоторых случаях приведут к потере информации.

Есть идеи для лучших решений?

1 ответ

Решение

Я думаю, что самое ленивое решение:

bool LessThan(dynamic left, dynamic right) {
    return left < right;
}

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

Это, кажется, дает желаемое поведение, но я подозреваю, что преобразования в некоторых случаях приведут к потере информации.

Если вы сравните Double и Single, C# преобразует Single к Double тем не мение. Их нельзя сравнивать иначе.

Другие вопросы по тегам