[英]can't pass default comparer as IComparer<object>
我正在尝试调用一个“Sort”方法,该方法需要IComparer<object>
类型的参数,使用以下代码:
collection.Sort((IComparer<object>)Comparer<DateTime>.Default)
它构建但在运行时我得到一个带有消息的InvalidCastException:
Unable to cast object of type
'System.Collections.Generic.GenericComparer`1[System.DateTime]'
to type 'System.Collections.Generic.IComparer`1[System.Object]'.
怎么办?
如果您想要的只是默认比较,这将有效:
collection.Sort(Comparer<object>.Default)
Comparer.Default使用对象的固有比较语义(即IComparable.CompareTo)。
不幸的是,您需要具有适当类型的比较器。
您可以创建一个自定义IComparer<object>
类,它只包含DateTime比较器,但是无法通过强制转换直接执行此操作。
如果您的集合始终包含DateTime对象,那么您可以这样做:
ICollection<DateTime> collection = ...;
collection.Sort(Comparer<DateTime>.Default); // or just collection.Sort()
阅读评论后编辑:
如果您直接使用ICollection,您可能希望使用LINQ选项来执行:
collection.Cast<DateTime>().OrderBy( date => date );
如果你正在使用实现IList<T>
东西(例如List<DateTime>
),你可以在列表本身上调用Sort()。
由于您使用的是非标准类,因此您需要制作自己的比较器:
class Comparer : IComparer<object> {
int Compare(object a, object b) {
return DateTime.Compare((DateTime)a, (DateTime)b);
}
}
然后你可以打电话:
collection.Sort(new Comparer() );
如果您可以更改集合对象的类型(即从List<object>
更改为ArrayList
),则可以使用非通用IComparer
接口( Comparer<DateTime>.Default
实现)。
如果你不能改变集合对象的类型,那你就不走运了。 (您总是可以实现一个实现IComparer<object>
,如下所示:
public class DateTimeComparer : IComparer<object>
{
public int Compare(object x, object y)
{
IComparer myComparer = Comparer<DateTime>.Default as IComparer;
return myComparer.Compare(x, y);
}
}
(如果您的集合中有任何非DateTime项目,这将抛出异常)
编辑:
你也可以实现一些更安全的东西,即:
public class DateTimeComparer : IComparer<object>
{
public int Compare(object x, object y)
{
if ( x is DateTime && y is DateTime )
{
return Comparer<DateTime>.Default.Compare((DateTime) x, (DateTime) y);
}
else
{
// handle the type mismatch
}
}
}
您可以像这样定义扩展函数:
public static class ComparerConversion
{
private class ComparerWrapper<T> : IComparer<object>
{
private readonly IComparer<T> comparer;
public ComparerWrapper(IComparer<T> comparer)
{
this.comparer = comparer;
}
public int Compare(object x, object y)
{
return this.comparer.Compare((T)x, (T)y);
}
}
public static IComparer<object> ToObjectComparer<T>(this IComparer<T> comparer)
{
return new ComparerWrapper<T>(comparer);
}
}
并像这样使用它:
List<object> collection = new List<object> { DateTime.Now.AddDays(1), DateTime.Now };
collection.Sort(Comparer<DateTime>.Default.ToObjectComparer());
只是尝试删除强制转换并让编译器选择IComparer
而不是IComparer<T>
。
Comparer<T>
实现IComparer<T>
和IComparer
因此它应该工作。
这很好用:
ArrayList collection = new ArrayList {DateTime.Now.AddDays(1), DateTime.Now};
collection.Sort(Comparer<DateTime>.Default);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.