如何解决通用OrderBy调用中缺少IComparable接口的编译时检测
当列表中的对象未实现IComparable接口时,通用方法OrderBy()或ThenBy()仅在运行时失败。像本例一样:
public class DataClass
{
public int Value { get; set; }
public DataClass(int value)
{
Value = value;
}
}
void Test()
{
var list = new List<DataClass>() { new DataClass(10),new DataClass(1),new DataClass(5) };
var sortedList = list.OrderBy(data => data).ToList(); // InvalidOperationException thrown by OrderBy()
}
有没有一种方法可以在编译时检测到此问题?
通过检测问题,我的意思是编译器向我显示以下错误:在OrderBy()调用中使用的lambda函数未返回实现IComparable接口的对象。我想查看编译时错误,而不是运行时错误。
我正在寻找最便宜的修补程序,该修补程序按易于实施的顺序排序:
- 打开一些编译器标志,该标志会警告我传递给OrderBy()的对象没有必需的接口。
- 使用某种代码分析器来检测缺少的接口。
- 如果无法使用#1和#2,则用现有的相当受欢迎的Nuget包中的内容替换LINQ扩展方法。
- 最后一个选择是用没有的LINQ方法替换那些没有显式定义所需接口的方法。
解决方法
在我回答这个问题时,我想我可能已经找到了不存在此约束的原因:Key
中的keySelector
类型可以实现 IComaprable<TKey>
或 IComparable
,我无法在约束中使用OR!
因此,鉴于这些信息,如果您想编写自己的扩展方法以添加类型约束,则对于每个重载,您将不得不编写其中两个(使用不同的名称),或者只需要选择将TKey
类型限制为哪个接口。
如果可以接受,请继续阅读我的原始答案...
我认为,此方法出现编译时错误的唯一方法是将其包装在您自己的扩展方法中,在调用IComparable<T>
方法之前,在其中添加Linq
约束:>
public static class Extensions
{
public static IEnumerable<TSource> OrderByConstrained<TSource,TKey>(
this IEnumerable<TSource> source,Func<TSource,TKey> keySelector)
where TKey : IComparable<TKey>
{
return source.OrderBy(keySelector);
}
}
现在在Data
类实现IComparable<DataClass>
之前,您将得到一个编译时错误:
var sortedList = list.OrderByConstrained(data => data);
// Compile Error CS0311: The type 'Test.Program.DataClass' cannot be used as type
// parameter 'TKey' in the generic type or method
// 'Extensions.OrderByConstrained<TSource,TKey>
// (IEnumerable<TSource>,TKey>)'.
// There is no implicit reference conversion from 'Test.Program.DataClass' to
// 'System.IComparable<Test.Program.DataClass>'.
然后实现该接口将解决编译错误:
public class DataClass : IComparable<DataClass>
{
public int Value { get; set; }
public DataClass(int value)
{
Value = value;
}
public int CompareTo(DataClass other)
{
return other == null ? 1 : Value.CompareTo(other.Value);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。