C# 隐藏基类的预期目的';没有警告的显式接口实现?
假设这些规范来自外部dll。显式实现接口的类:C# 隐藏基类的预期目的';没有警告的显式接口实现?,c#,interface,polymorphism,C#,Interface,Polymorphism,假设这些规范来自外部dll。显式实现接口的类: public interface IDebug { string GetImportantInfo(); } public class ExternalClass : IDebug { public void DoSomethingImportant() { System.Diagnostics.Debug.WriteLine("Something important was done..."); }
public interface IDebug
{
string GetImportantInfo();
}
public class ExternalClass : IDebug
{
public void DoSomethingImportant()
{
System.Diagnostics.Debug.WriteLine("Something important was done...");
}
string IDebug.GetImportantInfo() //Explicit implementation
{
DoSomethingImportant();
return nameof(ExternalClass);
}
}
然后这是来自内部代码的代码,您知道需要在其中实现接口:
public class Debug : ExternalClass, IDebug
{
public string GetImportantInfo()
{
return nameof(Debug);
}
}
现在,当我从子类调用Debug
的GetImportantInfo()
方法时,不会调用超类中的显式实现:
static void Main(string[] args)
{
IDebug test = new Debug();
var impInfo = test.GetImportantInfo();
System.Diagnostics.Debug.WriteLine(impInfo); //"Debug"
}
我似乎得到的唯一一点提示是,在未实现以下方法的情况下,将IDebug
接口添加到Debug
类时,不会出现编译错误:
public class Debug : ExternalClass, IDebug
{
}
为什么在覆盖超类的实现时没有编译警告?如果基类隐式地实现它,我会得到一个compile警告,告诉我使用new
关键字。但是使用new
关键字覆盖显式实现的方法会发出编译警告:
成员“Program.Debug.GetImportantInfo()”不隐藏继承的成员。新关键字不是必需的
这是有目的的,还是一个bug?如果是有意的,官方的理由是什么?如果您使用显式实现,那么方法在类中不可见,而不强制转换到接口。 你不能打电话了
new ExternalClass().GetImportantInfo()
但是你可以打电话
((IDebug)new ExternalClass()).GetImportantInfo();
由于显式实现,不需要新关键字。您甚至可以在一个类中添加两个实现:
public class ExternalClass : IDebug
{
string IDebug.GetImportantInfo() //Explicit implementation
{
return "Explicit";
}
public string GetImportantInfo()
{
return nameof(ExternalClass);
}
}
此外,调试类不必继承IDebug接口,因为它继承ExternalClass。Resharper会将此显示为冗余。这里的问题是您使用的是该语言的一个鲜为人知的功能:接口重新实现: 如果
ExternalClass
已经实现了IDebug
,为什么要重新声明Debug
实现了IDebug
?您正在重新实现接口,因为您正在做这样的事情,所以不会收到任何警告;编译器假定您知道自己在做什么
如果您想要看起来想要的行为,请不要重新实现接口:
public class Debug : ExternalClass, IDebug
{
public string GetImportantInfo()
{
return nameof(Debug);
}
}
如果基类隐式地实现它,我会得到一个compile警告,告诉我使用new关键字
此警告与接口实现无关。警告仅仅是由于方法隐藏,您有两个具有相同签名的方法IDebug
在这里不是一个因素,你可以把它排除在等式之外,你仍然会得到同样的警告
在我同事的例子中,他说他必须实现基类和接口,因为它是基于事件的接口
那么,告诉你的同事他想要什么。如果重新实现该接口,那么对DoSomething
的任何调用,无论是通过Debug
类型化引用还是IDebug
类型化引用,都应该调用重新实现的行为。任何其他行为都是出乎意料的,令人深感困惑
另一方面,如果通过IDebug
类型化引用调用DoSomething()
时需要保留基类的原始行为,则不要重新实现接口。你还有什么其他的选择
这是否意味着您应该知道基类实现了哪些接口?当然可以。老实说,我发现你的问题是,为什么任何人都应该知道你将从实现继承的任何给定类的接口,这让人深感不安。是的,但问题是为什么我可以隐藏基类的显式实现,而不会得到隐藏它的警告。如果
Debug
没有实现IDebug
,我调用test.GetImportantInfo()代码>如问题中所述,然后调用显式实现。遗憾的是,我目前没有ReSharper,但不管怎样-如果您想实现自己的基类隐式实现,可以调用base.GetImportantInfo()
。当它在基类中显式实现时,我将无法访问base.GetImportantInfo()
查看@Evk,当然它会改变一切((IDebug)debug).DoSomething()
将调用显式实现,debug.DoSomething()
不会。是的,我关于“无其他差异”的评论有误导性。但我仍然认为问题不在于此。OP继承了一些基类,想要实现IDebug接口,并且想要在该接口已经在基类中实现时发出警告,以避免意外地覆盖父实现。“简单的,不要这样做”。你是说你应该检查所有类实现的所有接口?我的同事遇到了这个问题,没有意识到超类也实现了这个接口。它假定“假定”您知道这一点,这一事实让我感到奇怪,因为当您隐藏隐式实现时,会收到编译警告。在我同事的例子中,他说他必须实现基类和接口,因为它是一个基于事件的接口。@AskeB。关于隐式实现的警告是一种误导。警告与接口无关,它只是一个隐藏警告的方法(请参见对我答案的编辑)。是的,如果您从一个类继承,那么您应该了解该类的所有相关信息,包括它实现的接口。这有什么好困惑的呢?@InBetween例如,如果在实现接口的那一个基类之间有15个基类,那么你认为期望每个人在实现接口之前检查整个链是合理的吗?150节课怎么样?1500班?不合理的数字,但希望你明白我的意思。无论如何,这意味着您希望所有程序员在他们的待办事项列表中记住这一点,而不仅仅是有一个编译警告
public class Debug : ExternalClass
{
public string GetImportantInfo()
{
return nameof(Debug);
}
}