2011-05-13 75 views
9

的类型调用的最具体方法这里总的OO noob问题。我有这两种方法中的一类为什么不是根据参数

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

我希望最上面的一个被调用。由于dbSession是LateSession类型的。

@Paolo Tedesco这是如何定义类的。

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


} 
+0

是否有一个特定的原因,你输入'var'而不是'LateSession'? – acron 2011-05-13 13:51:54

+8

@acron,什么是不输入'var'的原因? – detunized 2011-05-13 13:53:40

+0

@detunized,这只是我的看法,'var'是懒惰的,尤其是那时你像Saab一样为它分配一个特定的类型。为什么*不会*定义为'LateSession'?事实上,这整个问题不是反对使用'var'的证明吗? – acron 2011-05-13 13:59:35

回答

7

那么,你的假设是合理的,并有像你以为的地方工作过的语言。

所以做你的代码是这样的:

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

在第一个例子中,编译器prettends不知道什么实际类型“S的“并用Session参数硬编码该方法的调用。 在第二个例子中,编译器生成一个到另一个方法的硬编码调用。

在其他语言中,方法调用是“动态的”,这意味着在运行时会考虑实际类型。在它们的参数上多态的方法被称为“multimethods”(它们不仅在它们被定义的类中是多态的,而且在参数上也是多元的),因此“多”)

+0

一个很好的解释,我从来不知道这一点。进一步的谷歌搜索显示,C#和Java都不允许多次调度,但是Lisp和Python都可以。 – Zruty 2011-05-13 14:01:42

+2

但实际上,在这种情况下,**应该**按预期工作,因为该类型在编译时已知,并且应该调用正确的重载。可能还有一些其他问题,从示例中未显示出来...... – 2011-05-13 14:06:11

+0

该类型在编译时不是“真正”已知的。考虑通过参数调用的变量。我只把“新”放在那里,我们作为读者知道发生了什么; D – 2011-05-16 15:31:12

0

那个作业后的dbSession是什么类型?我会认为这是你的期望,但它可能是Session

另外,你是否真的需要用子类和父类重载这个方法?这似乎是一个奇怪的情况,你会同时需要这两个,并可能导致混淆。

+0

我把那个作为一个例子。所以dbSession是LateSession类型的。在我的代码运行时,我看到dbSession是LateSession类型,基类是Session。 我想这样做,所以我对不同类型有不同的行为。否则,我会诉诸超级讨厌的开关。 – Saab 2011-05-13 13:55:50

1

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

尝试失去了(LateSession, SessionViewModel)过载,并考虑LateSession在(Session, SessionViewModel)过载,如:

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

我认为这个问题是别的地方在你的代码。如果你尝试这个例子,事情如预期:

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

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