Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 隐藏基类的预期目的';没有警告的显式接口实现?_C#_Interface_Polymorphism - Fatal编程技术网

C# 隐藏基类的预期目的';没有警告的显式接口实现?

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..."); }

假设这些规范来自外部dll。显式实现接口的类:

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