C# 什么';这是比较器<;T>;上课时间?
如果指定的类型已经实现了C# 什么';这是比较器<;T>;上课时间?,c#,C#,如果指定的类型已经实现了IComparable,那么比较器类有什么用途 如果我指定Comparer.Default,并且Customer已经实现了IComparable,那么为什么我要使用Comparer类?该类型不需要实现IComparable,它可以是任何类型-对t没有任何约束: public abstract class Comparer<T> : IComparer, IComparer<T> 假设您有一个简单的类,Person,并且您想要对Person列表进行
IComparable
,那么比较器类有什么用途
如果我指定Comparer.Default,并且Customer已经实现了IComparable,那么为什么我要使用Comparer类?该类型不需要实现IComparable,它可以是任何类型-对t
没有任何约束:
public abstract class Comparer<T> : IComparer, IComparer<T>
假设您有一个简单的类,Person
,并且您想要对Person
列表进行排序,那么您最好编写一个比较器:
public class Person
{
string Name { get; set; }
}
比较器
保存实际的比较方法。如果您希望将对象与i可比较
实现中的对象进行不同的比较,则可以使用它。因为有时您需要将集合/有序队列按“自然”顺序或多个自然顺序进行排序
例如,如果有平面线,则可能需要按以下方式对其进行排序:
- 航班号
- 目的地
- 时间
- 优先权(某些航班可能比其他航班延误更长时间)
可以通过以下方式计划计算机中的任务:
- 使用者
- 优先级(在调度程序中)
- PID(正常比较)
因此,即使在一个应用程序中,也可能需要按不同的属性对对象进行排序。您不能通过int compareTo(Object)
方法实现这一点,因为它不能区分上下文。但是,您可以添加上下文,即实现CompareByPriority
我想您的问题是,为什么一个基类似乎只有一个有用的方法,而这个方法恰好是直接实现接口时要实现的方法。如果我理解正确,我想你是对的,与直接实现IComparer
相比,从Comparer
派生没有什么好处,除了基类为你提供了一个泛型和非泛型的实现以及一个重写的方法
但是,如果您的问题是为什么同时拥有IComparer
和IComparable
,那么
正如其他人所指出的,Comparer
允许您定义执行比较的不同方式。这是一个执行。一个很好的例子是各种StringComparer
属性,如StringComparer.Ordinal、StringComparer.OrdinalIgnoreCase等。这允许您在IComparable
接口无法预料的不同情况下对字符串进行不同排序
但除了能够重新定义执行比较的方式外,有时提供外部比较器是唯一的方法。例如,Windows窗体ListView类允许您为其排序逻辑指定IComparer。但是ListViewItem没有实现IComparable。因此,如果没有知道如何进行排序的比较器策略,ListViewItem是不可排序的,因为它没有默认的IComparable实现
因此,归根结底,这只是另一个扩展点,当您不是要排序的类型的作者(或者您需要多种排序策略)时,它允许您具有更大的灵活性
编辑:回应您下面的评论:“如果我有一个实现IComparer的类(我自己的类),这将允许我对任意数量的属性进行排序(自定义排序),那么我为什么还要麻烦使用Comparer.Default?”
也许举个例子会有所帮助。假设您正在编写一个扩展方法,该方法检查给定值是否在一个范围内
public static bool Between<T>(this T value, T minValue, T maxValue) {
var comparer = Comparer<T>.Default;
int c1 = comparer.Compare(value, minValue);
int c2 = comparer.Compare(value, maxValue);
return (c1 >= 0 && c2 <= 0);
}
public static bool-Between(此T值、T最小值、T最大值){
var comparer=comparer.Default;
int c1=比较器。比较(值,最小值);
int c2=比较器。比较(值,最大值);
return(c1>=0&&c2这里有几个微妙之处:
- 它不仅支持
IComparable
——它还支持旧的(非泛型)IComparable
作为回退。这意味着它不能仅仅表示为(例如)泛型约束
- 它支持
Nullable
,其中T
是可比较的,即使Nullable
显然不可IComparable
或IComparable
- 它通过不要求泛型类型约束来防止泛型类型约束的爆炸-例如,
列表
可以提供一个排序
,即使它并不坚持所有的t
都是可排序的;否则泛型约束的累积速度会很快,你会感到惊讶
- 它允许您将比较器传递到任何需要比较器的现有API中,而您所拥有的只是一个可比较的类型;大多数框架排序API(包括LINQ)都将提供比较器支持
公共级别人员
{
公共字符串LastName;
公共字符串名;
}
公共课2
{
公开无效测试()
{
List classList=新列表();
//向列表中添加一些数据
PersonComparer comp=新的PersonComparer();
classList.Sort(comp);
}
}
公共类人员比较者:比较者
{
公共覆盖整数比较(人员x、人员y)
{
int val=x.LastName.CompareTo(y.LastName);
如果(val==0)
{
val=x.FirstName.CompareTo(y.FirstName);
}
返回val;
}
}
如果一个类型实现了IComparable
,那么使用它几乎肯定比使用IComparable
要好。对于值类型,IComparable
的性能通常比非泛型的IComparable
好得多。对于可继承的引用类型,IComparable
可以提供更好的性能通过允许基于派生类型字段的排名,可以实现比
i可比较
对于后一个好处的示例,假设有一个抽象基类ScheduleEvent
,带有一个属性
public static bool Between<T>(this T value, T minValue, T maxValue) {
var comparer = Comparer<T>.Default;
int c1 = comparer.Compare(value, minValue);
int c2 = comparer.Compare(value, maxValue);
return (c1 >= 0 && c2 <= 0);
}
public class Person
{
public string LastName;
public string FirstName;
}
public class Class2
{
public void test()
{
List<Person> classList = new List<Person>();
//add some data to the list
PersonComparer comp = new PersonComparer();
classList.Sort(comp);
}
}
public class PersonComparer : Comparer<Person>
{
public override int Compare(Person x, Person y)
{
int val = x.LastName.CompareTo(y.LastName);
if (val == 0)
{
val = x.FirstName.CompareTo(y.FirstName);
}
return val;
}
}