比较实现 IComparable 的项目时出现问题
我正在研究一种扩展方法,它可以通过特定选择器找到最小项目。在代码下面
public static T MinBy<T, K>(this IEnumerable<T> src, Func<T, K> selector) where K : struct, IComparable, IConvertible
{
var min = default(K);
T minItem = default(T);
foreach (var item in src)
{
var current = selector(item);
if (current < min)
{
min = current;
minItem = item;
}
}
return minItem;
}
它给出了错误 Error Operator '<'不能应用于“K”和“K”类型的操作数
。但我已经指定通用约束 K 应该是 Struct 和 IComparable
。我相信所有的数值数据类型都可以满足这一点。
那为什么这是一个无效操作呢?
I am working on a extension method where it finds the min item by specific selector. Below the code
public static T MinBy<T, K>(this IEnumerable<T> src, Func<T, K> selector) where K : struct, IComparable, IConvertible
{
var min = default(K);
T minItem = default(T);
foreach (var item in src)
{
var current = selector(item);
if (current < min)
{
min = current;
minItem = item;
}
}
return minItem;
}
It gives error Error Operator '<' cannot be applied to operands of type 'K' and 'K'
. But i have specified the generic constraint K should be Struct and IComparable
. I believe all the numeric data type can be satisfied with this.
Then how come this is a invalid operation.?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
IComparable
没有(也不能)提及任何有关运算符的信息。您应该使用:运算符是静态的,并且仅重载而不是覆盖。您不能在接口中要求运算符,并且方法的存在不会神奇地改变运算符将执行的操作。 (例如,覆盖
Equals
不会改变==
的行为方式。)您还应该注意,因为您的约束仅讨论非泛型.Default。)
IComparable
界面,你将在每次操作中进行拳击。我建议您将约束更改为IComparable
。 (或者删除约束并按照 Marc 建议使用 Comparer有关您的方法的其他一些注释:
K 的默认值
(例如 K=int 并且所有键都是正数)那么您将找不到项目IComparare
的重载(但前提是您删除了可比较的约束)K
约束为值类型。如果我想找到字典中名字最早的人怎么办?T
的默认值;为了适应 LINQ 的其余部分,我建议抛出InvalidOperationException
TSource
和TKey
作为类型参数,以便与LINQ您可能需要查看 MoreLINQ MinBy 实现一个替代方案。 (再看一遍,我不确定要求
comparer
为非空对我们来说是个好主意;如果比较器为空。)IComparable
doesn't (and can't) say anything about operators. You should be using:Operators are static, and only ever overloaded rather than overridden. You can't require operators within interfaces, and the presence of a method doesn't magically change what an operator will do. (For example, overriding
Equals
does not change how==
behaves.)You should also note that as your constraint only talks about the nongeneric
IComparable
interface, you're going to be boxing at every operation. I would suggest you change the constraint toIComparable<K>
instead. (Or drop the constraint and just useComparer<K>.Default
as Marc suggested.)Some other comments about your method:
K
(e.g. K=int and all the keys are positive) then you won't find an itemIComparare<K>
(but only if you drop the comparable constraint)K
to a value type. What if I wanted to find the person with the lexicographically earliest name?T
; to fit in with the rest of LINQ I would suggest throwingInvalidOperationException
TSource
andTKey
as the type parameters to be more consistent with LINQYou may want to look at the MoreLINQ MinBy implementation as an alternative. (Looking over that again, I'm not sure it's a good idea for us to require that
comparer
is non-null; it should probably use the default comparer in the same way as normal LINQ does if the comparer is null.)IComparable
不提供运算符支持 - 您需要使用current.CompareTo(min)
。或者更好的是,使用 ComparerIComparable
doesn't provide operator support - you need to usecurrent.CompareTo(min)
. Or better, useComparer<T>.Default.Compare(current,min)
- then you can drop the constraint and it'll handle nulls etc automatically, and it'll avoid boxing.