我正在考虑为Min,Max等基本数学运算编写泛型函数.但是我不知道如何比较两种泛型类型:
public T Max<T>(T v1, T v2) where T: struct
{
return (v1 > v2 ? v1 : v2);
}
Run Code Online (Sandbox Code Playgroud)
那个怎么样?
谢谢.
Joe*_*oey 22
您可能希望限制要实现的泛型类型IComparable:
public T Max<T>(T v1, T v2) where T: struct, IComparable<T>
Run Code Online (Sandbox Code Playgroud)
然后使用CompareTo方法:
{
return (v1.CompareTo(v2) > 0 ? v1 : v2);
}
Run Code Online (Sandbox Code Playgroud)
Luk*_*keH 22
如果您只想创建比较函数,则可以使用该类型的默认比较器T.例如:
public static T Max<T>(T x, T y)
{
return (Comparer<T>.Default.Compare(x, y) > 0) ? x : y;
}
Run Code Online (Sandbox Code Playgroud)
如果是Timplements,IComparable<T>那么将使用该comparer; 如果T没有实现IComparable<T>但是实现IComparable那么将使用该比较器; 如果T没有实现任何一个IComparable<T>,IComparable那么将抛出运行时异常.
如果您希望/需要做的不仅仅是比较项目,那么您可以查看MiscUtil中的泛型运算符实现和相关文章.
让我不同意。@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使用反射时,这意味着运行时的成本很高,那么......,它不是通用的......为什么?
因为通用编程意味着:单个算法(通用)可以覆盖许多实现(对于许多类型),保持手写版本的效率。
举个例子。整数的手写版本是:
public static int Max( int x, int y)
{
return (x.CompareTo(y) > 0) ? x : y;
}
Run Code Online (Sandbox Code Playgroud)
它非常简单,仅涉及比较(或者可能更多,具体取决于 Int32.CompareTo() 的实现方式)。如果我们使用 @LukeH 的实现,我们将向非常简单的东西添加反射。
简而言之:
另一方面。 当 x 和 y 相等时,你认为 Max 应该返回什么?
我开始分析 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); });
}
Run Code Online (Sandbox Code Playgroud)
这在 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); });
}
Run Code Online (Sandbox Code Playgroud)
但是,这是不可能的,因为重载解析不考虑泛型约束......
那么,我就会有意识地离开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); });
}
Run Code Online (Sandbox Code Playgroud)