我有两个数据类: BaseDataClass 和 DerivedDataClass ,它们派生自第一个。 我还有两个消费类: ConsumingBaseClass 和 ConsumingDerivedClass ,它们派生自第一个。 在 ConsumingBaseClass 中,我有虚拟方法 DoWork ,它接受 DerivedDataClass < / strong>并做一些工作。
在 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; }
}
答案 0 :(得分:7)
有没有人知道,为什么要调用错误的方法?
根据语言规范调用正确的方法。这是你的期望,这是错误的。
在ConsumingDerivedClass中,我有方法DoWork的覆盖,并且我对DoWork也有重载,它接受BaseDataClass。
基本上这就是问题所在。重载分辨率不会像您认为的那样工作。编译器从调用目标的编译时类型开始工作,直到基类到object
。只考虑新声明的方法(甚至不被覆盖)。
您可以通过编写来更改将使用的重载:
((ConsumingBaseClass) x).DoWork(new DerivedDataClass());
理想情况下,如果你有一些这么脆弱的东西,那么给这些方法赋予不同的名称是值得的。过载应该具有相同的效果,只是以不同的方式提供信息。
基本上,请查看我brainteasers page上的第一个问题,以及第一个答案的详细信息。我也有article on overload resolution您可能会觉得有用。
答案 1 :(得分:1)
尝试更改基本方法以使用BaseDataClass并覆盖它。提供派生数据特定版本作为“新”方法(根据@Jon Skeet的回答)
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());
x.DoWork(new BaseDataClass());
Console.ReadKey();
}
}
public class ConsumingBaseClass
{
public virtual void DoWork(BaseDataClass instance)
{
Console.WriteLine("ConsumingBaseClass.DoWork(DerivedDataClass); Type of argument is '{0}'", instance.GetType());
}
}
public class ConsumingDerivedClass : ConsumingBaseClass
{
public override void DoWork(BaseDataClass instance)
{
Console.WriteLine("ConsumingDerivedClass.DoWork(DerivedDataClass); Type of argument is '{0}'", instance.GetType());
base.DoWork(instance);
// Some additional logic
}
public void DoWork(DerivedDataClass 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; }
}