简体   繁体   English

旨在隐藏基类的显式接口实现而不发出警告的预期目的?

[英]Intended purpose of hiding a base class' explicit interface implementation without warning?

Imagine these specifications are from an external dll. 想象一下,这些规范来自外部dll。 A class that implements an interface explicitly: 一个明确实现接口的类:

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

Then this one is from internal code, where you know you need to implement the interface: 然后这是来自内部代码的,您知道您需要实现该接口:

public class Debug : ExternalClass, IDebug
{
    public string GetImportantInfo()
    {
        return nameof(Debug);
    }
}

Now when I'm calling the Debug 's GetImportantInfo() method from the subclass, the explicit implementation in the superclass is not called: 现在,当我从子类中调用DebugGetImportantInfo()方法时,不会调用超类中的显式实现:

static void Main(string[] args)
{
    IDebug test = new Debug();
    var impInfo = test.GetImportantInfo();
    System.Diagnostics.Debug.WriteLine(impInfo); //"Debug"
}

And the only slight hint I seem to get is that I don't get a compile error when adding the IDebug interface to the Debug class, without implementing the method: 而且,我似乎得到的唯一一点提示是,在不实现该方法的情况下,将IDebug接口添加到Debug类时,不会出现编译错误:

public class Debug : ExternalClass, IDebug
{
}

Why is there no compile warning when you overwrite a superclass's implementation like this? 当您这样覆盖超类的实现时,为什么没有编译警告? If the base class implements it implicitly, I get a compile warning telling me to use the new keyword. 如果基类隐式实现它,则会收到编译警告,告诉我使用new关键字。 But using the new keyword to overwrite an explicitly implemented method gives a compile warning: 但是,使用new关键字覆盖显式实现的方法会产生编译警告:

The member 'Program.Debug.GetImportantInfo()' does not hide an inherited member. 成员“ Program.Debug.GetImportantInfo()”不会隐藏继承的成员。 The new keyword is not required. 不需要new关键字。

Is there an intended purpose for this, or is this a bug? 是否有此目的,还是一个错误? If it's intended, what is the official reasoning? 如果是故意的,官方的理由是什么?

The problem here is that you are using a little known feature of the language: interface re-implementation : 这里的问题是您正在使用该语言的一个鲜为人知的功能: 接口重新实现

public class Debug : ExternalClass, IDebug
{
    public string GetImportantInfo()
    {
        return nameof(Debug);
    }
}

Why are you redeclaring that Debug implements IDebug if ExternalClass already does? 如果ExternalClass已经做到了,为什么IDebug声明Debug实现了IDebug You are re-implementationing the interface, and becuase you are doing such thing, you get no warning; 您正在重新实现该接口,因为您正在执行此操作,所以不会收到任何警告。 the compiler assumes you know what you are doing. 编译器假定您知道自己在做什么。

If you want the behavior you seem to want, simply don't re-implement the interface : 如果您想要自己想要的行为,只需不要重新实现该接口即可

public class Debug : ExternalClass
{
    public string GetImportantInfo()
    {
        return nameof(Debug);
    }
}

If the base class implements it implicitly, I get a compile warning telling me to use the new keyword. 如果基类隐式实现它,则会收到编译警告,告诉我使用new关键字。

This warning has nothing to do with interface implementation. 此警告与接口实现无关。 The warning is simply due to method hiding, you have two methods with the same signature; 该警告仅是由于方法隐藏而引起的,您有两个具有相同签名的方法。 IDebug is a non factor here, you could put it out of the equation and you'd still get the same warning. 在这里, IDebug不是一个因素,您可以将其排除在等式之外,并且仍然会收到相同的警告。

In my colleague's case, he said he had to implement both the base class and the interface because it was an event-based interface. 对于我的同事,他说他必须同时实现基类和接口,因为它是基于事件的接口。

Well, then tell your colleague to figure out what he wants. 好吧,然后告诉您的同事弄清楚他想要什么。 If you reimplement the interface, then any call to DoSomething , be it through a Debug typed reference or an IDebug typed reference, should call the reimplemented behavior. 如果重新实现接口,则通过Debug类型的引用或IDebug类型的引用对DoSomething任何调用都应调用重新实现的行为。 Any other behavior would be unexpected and deeply bewildering. 任何其他行为都是意料之外的,并且令人深深困惑。

On the other hand, if you need to keep the orignal behavior of the base class if calling DoSomething() through a IDebug typed reference then do not re-implement the interface . 另一方面,如果通过IDebug类型的引用调用DoSomething()需要保持基类的原始行为,则不要重新实现该接口 What other alternative are you proposing? 您还建议其他什么选择?

Does this mean that you should know about what interfaces the base class implements? 这是否意味着您应该了解基类实现了哪些接口? Well yes, of course. 是的,当然。 I find your question about why should anyone know what interfaces any given class you are going to inherit from implements deeply worrisome to be honest. 我发现了您的问题,为什么有人应该知道您将从继承的任何给定类的接口实现,这实在令人担忧。

If you use Explicit implementation than method is not visible in your class without casting to interface. 如果使用Explicit实现,则在不强制转换为接口的情况下,方法在类中不可见。 You will not be able to call 您将无法拨打电话

new ExternalClass().GetImportantInfo()

but you can call 但是你可以打电话

((IDebug)new ExternalClass()).GetImportantInfo();

Because of Explicit implementation new keyword is not necessary. 由于显式实现,因此不需要新关键字。 You could even add both implementations in one class: 您甚至可以将两个实现添加到一个类中:

    public class ExternalClass : IDebug
    {
        string IDebug.GetImportantInfo() //Explicit implementation
        {
            return "Explicit";
        }
        public string GetImportantInfo() 
        {
            return nameof(ExternalClass);
        }
    }

Additionally your Debug class does not have to inherit IDebug interface as it inherits ExternalClass. 另外,您的Debug类不必继承IDebug接口,因为它继承了ExternalClass。 Resharper will show you this as redundant. Resharper将向您显示这是多余的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM