[英]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.