我有以下课程:
public class BaseRepository
{
public virtual void Delete(int id)
{
Console.WriteLine("Delete by id in BaseRepository");
}
}
public class EFRepository: BaseRepository
{
public override void Delete(int id)
{
Console.WriteLine("Delete by Id in EFRepository");
}
public void Delete(object entity)
{
Console.WriteLine("Delete by entity in EFRepository");
}
}
然后我就像使用它一样:
var repository = new EFRepository();
int id = 1;
repository.Delete(id);
为什么在这种情况下只会调用EFRepository.Delete(object entity)
?
答案 0 :(得分:27)
基本上,方法调用在C#中的工作方式是编译器首先查看派生类最多的类,并查看是否有任何新声明的方法(不包括覆盖)适用于呼叫。如果至少有一种适用的方法,那么重载决策就是最佳解决方案。如果没有,它会尝试基类,依此类推。
我同意这是令人惊讶的 - 它试图对抗脆弱的基类"问题,但我个人更喜欢任何重写的方法都包含在候选集中。
方法调用在C#5规范的7.6.5.1节中描述。这里的相关部分是:
- 候选方法集合被简化为仅包含来自大多数派生类型的方法:对于集合中的每个方法
C.F
,其中C
是方法F
的类型声明后,从基类型C
声明的所有方法都将从集合中删除。此外,如果C
是除object之外的类类型,则从集合中删除在接口类型中声明的所有方法。 (后一条规则仅在方法组是对具有除object之外的有效基类和非空有效接口集的类型参数进行成员查找的结果时才会生效。)
在7.4的成员查找部分中,override
方法被明确删除:
包含
override
修饰符的成员将从集合中排除。
答案 1 :(得分:0)
因为:public override void Delete(int id)将仅覆盖基类方法中的哪一个:public virtual void Delete(int id)。
虽然public void Delete(对象实体)是 EFRepository类方法,但是当您从EFRepository对象执行方法时,它将调用自己的方法这只是公共空白删除(对象实体)