方法重载和继承

本文关键字:继承 重载 方法 | 更新日期: 2023-09-27 18:04:51

我有以下类:

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)会调用?

方法重载和继承

基本上,c#中方法调用的工作方式是编译器首先查看最派生的类,并查看是否有任何新声明的方法(不包括覆盖)适用于调用的参数。如果至少有一种适用的方法,重载解析就会计算出哪一种是最好的。如果没有,则尝试基类,依此类推。

我同意这是令人惊讶的——它试图对抗"脆弱的基类"问题,但我个人更喜欢任何被覆盖的方法都包含在候选集中。

方法调用在c# 5规范的7.6.5.1节中描述。这里的相关部分是:

  • 候选方法集被简化为只包含来自最多派生类型的方法:对于集合中的每个方法C.F,其中C是声明方法F的类型,所有在C的基类型中声明的方法都从集合中删除。此外,如果C是类类型而不是对象,则在接口类型中声明的所有方法都将从集合中删除。(后一条规则仅在方法组是对具有有效基类而非对象和非空有效接口集的类型参数进行成员查找的结果时有效。)

在7.4的成员查找部分,override方法被显式删除:

包含override修饰符的成员被排除在集合之外。

因为:public override void Delete(int id)将只重写基类方法其中一个:public virtual void Delete(int id)

而public void Delete(对象实体)是EFRepository类方法,所以当你从EFRepository对象执行方法时,它将调用自己的方法,这只是公共void Delete(对象实体)