.net选择错误的方法来调用,基于aruments类型

And*_*ris 1 c# overloading derived-class

我有两个Data类:BaseDataClassDerivedDataClass,它们派生自第一个.我还有两个Consuming类:ConsumingBaseClassConsumingDerivedClass,它们派生自第一个.在ConsumingBaseClass中,我有虚拟方法DoWork,它接受DerivedDataClass并做一些工作.

ConsumingDerivedClass中,我对方法DoWork进行了覆盖,并且我对DoWork也有重载,它接受BaseDataClass.当我尝试调用DoWork的,路过的实例DerivedDataClass,DoWork的(BaseDataClass)被称为替代的DoWork(DerivedDataClass) .

有什么想法,为什么叫错方法?

以下代码阐述了问题:

class Program
{
    private static void Main(string[] args)
    {
        ConsumingDerivedClass x = new ConsumingDerivedClass();
        // Wrong DoWork is called - expected calling of DoWork(DerivedDataClass) but actually called DoWork(BaseDataClass)
        x.DoWork(new DerivedDataClass());
        Console.ReadKey();
    }
}

public class ConsumingBaseClass
{
    public virtual void DoWork(DerivedDataClass instance)
    {
        Console.WriteLine("ConsumingBaseClass.DoWork(DerivedDataClass); Type of argument is '{0}'", instance.GetType());
    }
}

public class ConsumingDerivedClass : ConsumingBaseClass
{
    public override void DoWork(DerivedDataClass instance)
    {
        Console.WriteLine("ConsumingDerivedClass.DoWork(DerivedDataClass); Type of argument is '{0}'", instance.GetType());
        base.DoWork(instance);
        // Some additional logic
    }

    public void DoWork(BaseDataClass instance)
    {
        Console.WriteLine("ConsumingDerivedClass.DoWork(BaseDataClass); Type of argument is '{0}'", instance.GetType());
        DerivedDataClass derivedInstance = new DerivedDataClass();
        // Some logic based on what is in baseInstacne
        derivedInstance.SomeProperty = "Value, got from some logic";

        base.DoWork(derivedInstance);
        // Some additional logic
    }
}

public class BaseDataClass
{ }

public class DerivedDataClass : BaseDataClass
{ 
    public string SomeProperty { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 7

有什么想法,为什么叫错方法?

根据语言规范调用正确的方法.这是你的期望是错误的.

在ConsumingDerivedClass中,我对方法DoWork进行了覆盖,并且我对DoWork也有重载,它接受BaseDataClass.

基本上这就是问题所在.重载分辨率不会像您认为的那样工作.编译器从调用目标的编译时类型开始工作,直到基类object.仅考虑新声明的方法(甚至不被覆盖).

您可以通过编写来更改将使用的重载:

((ConsumingBaseClass) x).DoWork(new DerivedDataClass());
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果你有一些这么脆弱的东西,那么给这些方法赋予不同的名称是值得的.过载应该具有相同的效果,只是以不同的方式提供信息.

基本上,看看我的脑筋急转弯页面上的第一个问题,以及第一个答案的细节.我还有一篇关于重载决策文章,您可能会发现它很有用.