开发者

Why isn't the most specific method called based on type of parameter

Total OO noob question here. I have these two methods in a class

private void StoreSessionSpecific(LateSession dbSession, SessionViewModel session)
{
    session.LateSessionViewModel.Guidelines = dbSession.Guidelines.ToList();
}

private void StoreSessionSpecific(Session dbSession, SessionViewModel session )
{
        // nothing to do yet...
}

And when I call StoreSessionSpecific with dbSession being of type LateSession (LateSession inherits Session)

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

I expected the top one to be called. Since dbSession is of type LateSession.

@Paolo Tedesco This is how the classes are defined.

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 in开发者_运维技巧t MaxResultCriticalIncidents { get; set; }

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


}


Well, your assumption is plausible and there are languages where it had worked like you thought.

So does your code look like this:

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

or does it look like this:

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

In the first example the compiler prettends not to know what the actual type of "s" is and hard codes the invocation of the method with the Session argument. In the second example likewise the compiler generates a hard coded call to the other method.

In other languages the method call is "dynamic", that means during runtime the actuall types are considered. Methods that are polymorphic on their arguments are called "multimethods" (They are not only polymorphic on the class they are defined in but also on the arguments, hence "multi") (Edit: fixed typos)


I think the problem is somewhere else in your code. If you try this example, things work as expected:

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();
    }
}

Could you post a complete example? maybe there's a problem with the class definitions...


I apologize for not knowing the specifics of why this happens, but I have an idea on how to work around it.

Try loosing the (LateSession, SessionViewModel) overload, and account for LateSession in the (Session, SessionViewModel) overload like:

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


As Angel O'Sphere said, C# doesn't have multiple dispatch however you can implement double dispatch using Visitor Pattern.

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


What is the type of dbSession after that assignment? I would assume it is what you expect, but it could be a Session.

Separately, do you really need to overload this method with both a child and parent class? It seems like a strange case where you would need both, and will likely lead to confusion.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜