继承iccomparable 的接口引用对象排序列表
本文关键字:引用 对象 排序 列表 接口 iccomparable 继承 | 更新日期: 2023-09-27 17:55:04
对于指向不同类型的接口引用列表,我在list.Sort()中遇到了麻烦,但是问题Sort a list of interface objects提供了以下解决方案
interface IFoo : IComparable<IFoo>
{
int Value { get; set; }
}
class SomeFoo : IFoo
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
在我的原始代码中,而不是IFoo从iccomparable继承,我的类同时继承了IFoo和iccomparable,即
interface IFoo
{
int Value { get; set; }
}
class SomeFoo : IFoo, IComparable<IFoo>
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
class SomeBar : IFoo, IComparable<IFoo>
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
}
}
但是当我试图对IFoo引用列表进行排序时,我得到了错误Failed to compare two elements in the array.
。
List<IFoo> iFoos = new List<IFoo>
{
new SomeFoo{Value = 1},
new SomeFoo{Value = 15},
new SomeFoo{Value = 390},
new SomeBar{Value = 2},
new SomeBar{Value = 78},
new SomeBar{Value = 134}
}
iFoos.Sort();
谁能解释为什么我原来的代码不能工作?
您的列表是IFoo
的列表。因此,从列表(及其排序操作)的角度来看,它只看到接口,而不知道具体类型的任何信息。
所以当它试图订购两个IFoo
时,它不能这样做,因为IFoo
不实现IComparable
。
IComparable<Foo>
,所以不能保证列表中的所有 IFoo
元素都这样做。因此操作是不安全的。
为了能够使用IComparable<IFoo>
对元素进行排序,IFoo
接口需要实现接口本身。
或者,您也可以实现IComparer<IFoo>
并将其传递给Sort()
,然后将其委托给各自的实际实现。当然,这并不是一个真正优雅的解决方案,也不是很未来的证明(如果您创建了IFoo
的新实现):
class FooComparer : IComparer<IFoo>
{
public int Compare(IFoo a, IFoo b)
{
if (a is SomeFoo)
return ((SomeFoo)a).CompareTo(b);
else if (a is SomeBar)
return ((SomeBar)a).CompareTo(b);
else
throw new NotImplementedException("Comparing neither SomeFoo nor SomeBar");
}
}
当然,如果您的意思是IFoo
是可比较的,您应该让该接口直接实现IComparable<IFoo>
,而不是依靠子类型来实现。IFoo
是一个契约,可排序是一个很好的属性。
很好的问题!
当你对一个类型进行排序时,你希望这个类型实现icomcomparable。
在你的原始代码中,你正在排序IFoo
,它不实现IComparable
,但在第二个代码中它做到了。这就是一切的不同。
但是如果你有一个List<SomeBar>
的集合,它会排序,因为它有IComparable实现。忽略您可能需要使用List的接口,我建议您使用第二个解决方案。
此行为在文档中有描述:
该方法对类型T使用默认比较器
Comparer<T>.Default
确定列表元素的顺序。的Comparer<T>.Default
属性检查类型T是否实现了icomable泛型接口并使用该实现(如果可用)。如果不是这样,比较器。Default检查类型T是否实现IComparable接口。如果类型T没有实现任何接口,比较器。Default抛出InvalidOperationException。
由于T
是IFoo
,当IFoo
实现IComparable<IFoo>
时,您的第一个示例工作,而第二个示例失败,因为它没有。我建议您创建一个类FooComparer : IComparer<Foo>
并将其传递给Sort的另一个重载。
在第一个示例中,IFoo
实现了IComparable<IFoo>
,而在第二个示例中没有。如果您使用Array.Sort
或任何其他排序例程,它将导致ArgumentException
,至少有一个对象应该实现IComparable
。