C# 比较器中的方法分辨率
考虑以下基本类布局:C# 比较器中的方法分辨率,c#,overloading,derived,C#,Overloading,Derived,考虑以下基本类布局: public class Base : IComparable<Base> { public int CompareTo(Base other) { //Do comparison } } public class Derived : Base, IComparable<Derived> { public int CompareTo(Derived other) { //Do comparison } }
public class Base : IComparable<Base>
{
public int CompareTo(Base other)
{
//Do comparison
}
}
public class Derived : Base, IComparable<Derived>
{
public int CompareTo(Derived other)
{
//Do comparison
}
}
public class BaseComparer : IComparer<Base>
{
public int Compare(Base x, Base y)
{
return x.CompareTo(y);
}
}
公共类基:IComparable
{
公共整数比较(基本其他)
{
//做比较
}
}
派生的公共类:基类,IComparable
{
公共整数比较(派生其他)
{
//做比较
}
}
公共类基比较器:IComparer
{
公共整数比较(基数x,基数y)
{
返回x.CompareTo(y);
}
}
然后使用以下各项:
List<Base> thingies = new List<Base>
{
new Base(),
new Derived(),
new Derived()
};
thingies.Sort(new BaseComparer());
List thingies=新列表
{
新基(),
新的派生(),
新派生()
};
Sort(newbasecomparer());
在x和y参数都是派生实例的情况下,我希望比较器调用Derived.CompareTo方法
然而,情况并非如此,而是调用Base.CompareTo,我一直在想为什么。根据我对C语言规范中描述的重载解析规则的基本理解,我似乎无法推断这种行为
有人能帮我解释一下吗?
Base
不知道它的派生类,所以在Base
中只有一个CompareTo
方法,它被无条件调用
关键是重载解析发生在编译时,在编译时没有关于Base
引用的实际类型的信息。您需要重写派生的
中的方法,而不是重载它:
并另外标记基。与方法虚拟进行比较
请注意,这不再实现IComparable
。您也可以这样做,但出于您的目的,这是不相关的。Base
对其派生类一无所知–因此在Base
中只有一个CompareTo
方法,该方法将无条件调用
关键是重载解析发生在编译时,在编译时没有关于Base
引用的实际类型的信息。您需要重写派生的
中的方法,而不是重载它:
并另外标记基。与方法虚拟进行比较
请注意,这不再实现IComparable
。您也可以这样做,但出于您的目的,这是不相关的。这里发生的不是过载解决。您有两个独立的方法:它们的全名是IComparable.CompareTo
和IComparable.CompareTo
BaseComparer
唯一知道如何调用的是IComparable.CompareTo
。它对i可比性一无所知
在您的应用程序中,将Base
与派生的进行比较有意义吗?也就是说,可以说Base
位于派生的之前或之后
- 如果是这样,您最好只使用
IComparable
,甚至使用非泛型的IComparable
,并准备检查子类中的类型
如果不,则应考虑制作 Base<代码> >,只在叶类上执行<代码>可比较的< /代码> >
这里发生的不是过载解决。您有两个独立的方法:它们的全名是
IComparable.CompareTo
和IComparable.CompareTo
BaseComparer
唯一知道如何调用的是IComparable.CompareTo
。它对i可比性一无所知
在您的应用程序中,将Base
与派生的进行比较有意义吗?也就是说,可以说Base
位于派生的之前或之后
- 如果是这样,您最好只使用
IComparable
,甚至使用非泛型的IComparable
,并准备检查子类中的类型
如果不,则应考虑制作 Base<代码> >,只在叶类上执行<代码>可比较的< /代码> >
IComparable
和IComparable
是两种不同的类型,因此派生的
中的两种方法比较
映射到两个不同的插槽上CompareTo
由BaseComparer
调用IComparable
的方法调用。您可以将Base
中的CompareTo(Base)
表示为virtual
,并在Derived
中重写它以获得(部分)预期行为
public class Base : IComparable<Base>
{
public virtual int CompareTo(Base other)
{
// do comparison
}
}
public class Derived : Base, IComparable<Derived>
{
public int CompareTo(Derived other)
{
// do comparison
}
public override int CompareTo(Base other)
{
if (other is Derived)
return CompareTo((Derived) other);
return base.CompareTo(other);
}
}
公共类基:IComparable
{
公共虚拟整数比较(基本其他)
{
//做比较
}
}
派生的公共类:基类,IComparable
{
公共整数比较(派生其他)
{
//做比较
}
公共覆盖整数比较(基本其他)
{
如果(其他是派生的)
返回CompareTo((派生)其他);
返回基数。比较(其他);
}
}
IComparable
和IComparable
是两种不同的类型,因此派生的
中的两种方法比较
映射到两个不同的插槽CompareTo
由BaseComparer
调用IComparable
的方法调用。您可以将Base
中的CompareTo(Base)
表示为virtual
,并在Derived
中重写它以获得(部分)预期行为
public class Base : IComparable<Base>
{
public virtual int CompareTo(Base other)
{
// do comparison
}
}
public class Derived : Base, IComparable<Derived>
{
public int CompareTo(Derived other)
{
// do comparison
}
public override int CompareTo(Base other)
{
if (other is Derived)
return CompareTo((Derived) other);
return base.CompareTo(other);
}
}
公共类基:IComparable
{
公共虚拟整数比较(基本其他)
{
//做比较
}
}
派生的公共类:基类,IComparable
{
公共整数比较(派生其他)
{
//做比较
}
公共覆盖整数比较(基本其他)
{
如果(其他是派生的)
返回CompareTo((派生)其他);
返回基数。比较(其他);
}
}
阅读Eric Lipperts关于过载解决方案的博客文章-阅读Eric Lipperts关于过载解决方案的博客文章-感谢您的努力。我试着变得聪明些,防止这种情况发生