方法重载和继承

24

我有以下几个类:

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


对象可以保存一个整数。 - Travis J
@TravisJ 我很了解这个问题,但是问题有点不同。 - Roman Marusyk
2个回答

28

在C#中,方法调用的方式基本上是编译器首先查看最派生的类,并查看该调用的参数是否适用于任何新声明的方法(不包括覆盖)。如果有至少一个适用的方法,则会进行重载解析以确定哪个是最佳的方法。如果没有可用的方法,则会尝试基类,以此类推。

我认为这很令人惊讶 - 这是试图解决“脆弱的基类”问题的一种尝试,但我个人更喜欢包括所有已覆盖的方法在候选集中。

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

  • 将候选方法集简化为仅包含最派生类型中的方法:对于集合中的每个方法 C.F,其中 C 是声明方法 F 的类型,则从 C 的基类型中删除所有声明的方法。此外,如果 C 是除 object 之外的类类型,则从接口类型中删除所有声明的方法。(当方法组是对具有非空有效接口集且具有有效基类的类型参数进行成员查找的结果时,后面的规则才会起作用。)

在第7.4的成员查找部分中,override方法明确被排除在外:

包括 override 修饰符的成员将从集合中排除。


谢谢您的解释。所以,没有办法直接调用带有int参数的方法,对吗? - Roman Marusyk
1
@MegaTron:你首先必须转换为BaseRepository。 - Jon Skeet
谢谢。我认为修改那个设计会更好。 - Roman Marusyk
“新声明的方法(不仅仅是重写的方法)”这个短语是否排除了重写的方法?如果是,那么“just”使它变得令人困惑。 - piedar

0

因为:public override void Delete(int id) 只会覆盖基类方法之一:public virtual void Delete(int id)。

而 public void Delete(object entity) 是 EFRepository 类的方法,所以当您从 EFRepository 对象执行该方法时,它将调用自己的方法,即 public void Delete(object entity)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接