我的代码有问题。
我希望这样做,因为我正在构建Implementation对象;每次调用Method()时,我都会使用实际的Implementation.Method(),而不是抽象的Base.Method()。不得不向下转换到实际的实现程序或显式指定接口似乎不合理(因此,接口在C#中不是可传递的?我将称为“接口实现程序的第一个正确实例”,而不是我的类?)
我有一个与此类似的结构(为清楚起见简化了): https://dotnetfiddle.net/oYVlQO
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public string Method() { return "Sample"; }
}
public class Implementation : Base // if I add ", IBase" to this it works as expected, but why?
{
new public string Method() { return "Overriden"; }
}
public class Program
{
// and it's used like so...
public static void Main()
{
IBase b = new Implementation();
//Implementation b = new Implementation(); // It works as expected, always using Implementation.Method();
Console.WriteLine(b.Method()); // Produces "Sample", so Base.Method(). Why not implementation?
Console.WriteLine(((Implementation) b).Method()); // Produces "Overriden", so Implementation.Method(); Since when I have to downcast to use overriden method!?
}
}
}
我真的很想为此解决;尤其是Java中的相同代码可以“如我所愿” https://repl.it/repls/VitalSpiritedWebpage
我试图在c#规范中找不到它,也许我没有正确的关键字...
答案 0 :(得分:2)
引起问题的原因是: 为什么会这样呢? 我的答案: 因为您不重写方法而是将其隐藏。 该接口由基类实现,因此在基类上调用Method。 要回答未问的问题: 它将如何工作?
答案:
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public virtual string Method() { return "Sample"; }
}
public class Implementation : Base
{
public override string Method() { return "Overriden"; }
}
答案 1 :(得分:1)
您可能想看一下C#规范中涉及interface re-implementation.的部分
当您通过接口访问成员时,它将开始在显式实现该接口的最派生类型上进行查找。在您的示例中,最派生的类型是Base
,因此它将调用那里存在的方法。
当您将IBase
添加到Implementation
明确实现的接口列表中时,它可以工作,因为这是查找的新起点,并且可以找到您的新方法。
您可以通过将基本成员虚拟化,然后在派生类中覆盖它来解决您的问题,也可以通过将其包含在Implementation
类的列表中来重新实现该接口。
答案 2 :(得分:1)
所以我的示例代码中的问题有两个。
我假设在C#中,默认情况下方法是“虚拟的”(与Java中一样)。由于我通常使用Java进行编码,因此我做出了错误的假设。
请参见Is it possible to override a non-virtual method?
如果我使用虚拟的,我可以重写该方法并准确实现我期望的输出,如doc中所述:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/virtual即“当调用虚拟方法时,将检查对象的运行时类型是否有覆盖成员。将调用派生程度最高的类中的覆盖成员,该成员可能是原始成员,如果没有派生类已重写该成员。”
我的代码更喜欢使用方法隐藏,所以除非我通知编译器我打算使用我的实现的意图,否则它将默认为非隐藏方法(由抽象类作为实际的原始实现者解决)< / p>