簡體   English   中英

無法將默認比較器作為IComparer傳遞<object>

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM