无法将默认比较器作为IComparer <object> </object>传递

时间:2009-09-03 18:59:08

标签: c# generics llblgenpro

我正在尝试使用以下代码调用“排序”方法,该方法需要类型为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]'.

现在是什么?

5 个答案:

答案 0 :(得分:7)

如果您想要的只是默认比较,那么这将起作用:

collection.Sort(Comparer<object>.Default)

Comparer.Default使用对象的固有比较语义(即IComparable.CompareTo)。

答案 1 :(得分:4)

不幸的是,你需要有一个合适类型的比较器。

您可以创建一个自定义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() );

答案 2 :(得分:3)

如果您可以更改集合对象的类型(即从ArrayList更改为List<object>),那么您可以使用非通用IComparer接口({{{ 1}}实现)。

如果您无法更改集合对象的类型,那么您就不走运了。 (您总是可以实现一个实现Comparer<DateTime>.Default的对象,如下所示:

IComparer<object>

(如果您的集合中有任何非DateTime项目,则会抛出异常)

编辑:

你也可以实现一些更安全的东西,即:

 public class DateTimeComparer : IComparer<object>
    {       
        public int Compare(object x, object y)
        {
            IComparer myComparer = Comparer<DateTime>.Default as IComparer;
            return myComparer.Compare(x, y);
        }     
    }

答案 3 :(得分:3)

您可以像这样定义扩展函数:

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());

答案 4 :(得分:1)

尝试删除演员表,让编译器选择IComparer而不是IComparer<T>

Comparer<T>同时实现了IComparer<T>IComparer,因此它应该有效。

这很好用:

ArrayList collection = new ArrayList {DateTime.Now.AddDays(1), DateTime.Now};
collection.Sort(Comparer<DateTime>.Default);