为什么不根据参数类型调用最具体的方法

本文关键字:方法 调用 参数 类型 为什么不 | 更新日期: 2023-09-27 17:56:26

这里的 OO 菜鸟问题。我在一堂课上有这两个方法

private void StoreSessionSpecific(LateSession dbSession, SessionViewModel session)
{
    session.LateSessionViewModel.Guidelines = dbSession.Guidelines.ToList();
}
private void StoreSessionSpecific(Session dbSession, SessionViewModel session )
{
        // nothing to do yet...
}

当我调用 StoreSessionSpecific 时,dbSession 的类型为 LateSession(LateSession 继承会话)

var dbSession = new LateSession();
StoreSessionSpecific(dbSession, session);

我以为会叫最上面的那个。由于数据库会话的类型是 LateSession。

@Paolo特德斯科 这就是类的定义方式。

public class Session
{
    public int ID { get; set; }
    public int SessionTypeId { get; set; }
    public virtual SessionType SessionType { get; set; }
    [Required]
    public DateTime StartTime { get; set; }
    [Required]
    public DateTime EndTime { get; set; }
    // Session duration in minutes
    // public int SessionDuration { get; set; }
    public virtual ICollection<Attendee> Attendees { get; set; }
}
public class LateSession : Session
{

    public int MaxCriticalIncidentsPerUser { get; set; }
    public int MaxResultCriticalIncidents { get; set; }
    public virtual ICollection<Guideline> Guidelines { get; set; }

}

为什么不根据参数类型调用最具体的方法

嗯,你的假设是合理的,有些语言就像你想象的那样工作。

所以你的代码看起来像这样:

Session s = new LateSession(); // the compiler only "knows" that s is of type Session
StoreSessionSpecific(s);

或者它看起来像这样:

LateSession ls = new LateSession(); // the compiler knows that ls is in fact a LateSession
StoreSessionSpecific(ls);

在第一个示例中,编译器假装不知道"s"的实际类型是什么,并使用 Session 参数对方法的调用进行硬编码。同样,在第二个示例中,编译器生成对另一个方法的硬编码调用。

在其他语言中,方法调用是"动态的",这意味着在运行时会考虑精算类型。在其参数上是多态的方法称为"多方法"(它们不仅在定义它们的类上是多态的,而且在参数上也是多态的,因此是"多的")(编辑:修正错别字)

我认为问题出在您的代码中的其他地方。如果您尝试此示例,事情将按预期工作:

class Base { 
}
class Derived : Base { 
}
class Something {
    private void DoSomething(Base b) {
        Console.WriteLine("DoSomething - Base");
    }
    private void DoSomething(Derived d) {
        Console.WriteLine("DoSomething - Derived");
    }
    public void Test() {
        var d = new Derived();
        DoSomething(d);
    }
}
static class Program {
    static void Main(params string[] args) {
        Something something = new Something();
        something.Test();
    }
}

你能发布一个完整的例子吗? 也许类定义有问题...

我很抱歉不知道为什么会发生这种情况的细节,但我有一个关于如何解决它的想法。

尝试丢失(LateSession, SessionViewModel)重载,并在(Session, SessionViewModel)重载中考虑 LateSession,如下所示:

private void StoreSessionSpecific(Session dbSession, SessionViewModel session )
{
   if (dbSession is LateSession) { 
      // handle as LateSession
   } else { 
      // handle as base-class Session
   }
}

正如 Angel O'Sphere 所说,C# 没有多重调度,但是您可以使用访客模式实现双重调度。

http://en.wikipedia.org/wiki/Visitor_pattern

作业后的dbSession类型是什么? 我认为这是您所期望的,但这可能是一个Session.

另外,你真的需要使用子类和父类重载此方法吗? 这似乎是一个奇怪的情况,您需要两者,并且可能会导致混乱。