Позвольте мне не согласиться.
Реализация @ LukeH не является общей .
Я объясню, почему это не Generic:
Comparer<T>.Default
включает проверку T во время выполнения, чтобы определить, реализует ли он IComparable<T>
, IComparable
или нет.
Хотя это поведение недостаточно документировано в http://msdn.microsoft.com/en-us/library/azhsac5f.aspx,, мы можем вычесть его, потому что Comparer<T>.Default
выдает исключение, когда T не реализует ни того, ни другого. Если бы проверка была выполнена во время компиляции, исключение (время выполнения) не потребовалось бы, с ошибкой времени компиляции.
Тогда, так как Comparer<T>.Default
использует Reflection, это означает высокую стоимость времени выполнения, тогда ...., Это НЕ универсальный ... Почему?
Поскольку Общее программирование означает: Один алгоритм (Универсальный) может охватывать множество реализаций (для многих типов), поддерживая эффективность рукописных версий.
Возьмите пример. Рукописная версия для целых чисел будет:
public static int Max( int x, int y)
{
return (x.CompareTo(y) > 0) ? x : y;
}
Это очень просто, включая только сравнение (или, может быть, больше, в зависимости от того, как реализовано Int32.CompareTo ()).
Если мы используем реализацию @ LukeH, мы добавляем Reflection к чему-то очень простому.
Короче говоря:
- Всегда предпочитайте ошибки времени компиляции исключениям времени выполнения (это не Javascript, Ruby, ... :-))
- Эта реализация менее эффективна по сравнению с рукописной версией (для любого типа)
С другой стороны.
Что, по вашему мнению, должен вернуть Макс, когда x и y являются эквивалентами?
Я начинаю анализировать реализации Real-Generic ....
Идеальной реализацией было бы что-то вроде ...
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
//Pseudo-code ( note the 'or' next to 'where' )
public static T Max<T>(T x, T y) where T: IComparable<T> or IComparable
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
Это невозможно в C #, следующая попытка может быть ...
//pseudo-code
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
public static T Max<T>(T x, T y) where T: IComparable<T>
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
public static T Max<T>(T x, T y) where T: IComparable
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}
Но это невозможно, поскольку разрешение перегрузки не учитывает общие ограничения ....
Тогда я сознательно пропущу IComparable
. Я просто буду беспокоиться о IComparable<T>
public static T Max<T>(T x, T y, Func<T, T, int> cmp)
{
return (cmp(x, y) > 0) ? x : y;
}
public static T Max<T>(T x, T y) where T: IComparable<T>
{
return Max(x, y, (a, b) => { return a.CompareTo(b); });
}