What is the intended purpose of hiding the implementation of an explicit base class interface without warning?

Imagine that these specifications are taken from an external dll. A class that explicitly implements the interface:

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 is one of the internal code where you know that you need to implement the interface:

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

Now, when I call the Debug GetImportantInfo() method from a subclass, the explicit implementation in the superclass is not called:

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

And the only easy hint, which, it seems to me, is that I do not get a compilation error when adding the IDebug interface to the Debug class without implementing the method:

 public class Debug : ExternalClass, IDebug { } 

Why is there no compilation when you overwrite a superclass implementation like this? If the base class implements it implicitly, I get a compilation warning telling me to use the new keyword. But using the new keyword to overwrite an explicitly implemented method gives a compilation warning:

The user 'Program.Debug.GetImportantInfo ()' does not hide the inherited element. A new keyword is not required.

Is there a purpose for this, or is it a mistake? If this is intended, what is the official reasoning?

+5
source share
2 answers

The problem is that you are using a little-known language feature: reimplementing the interface:

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

Why are you updating Debug implement IDebug if ExternalClass already does? You reimplement the interface, and since you are doing such a thing, you are not getting warnings; the compiler assumes that you know what you are doing.

If you need behavior that you think is desirable, just don’t repeat the interface implementation:

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

If the base class implements it implicitly, I get a compilation warning saying that I am using a new keyword.

This warning has nothing to do with the implementation of the interface. The warning is simply due to a method hiding, you have two methods with the same signature; IDebug is not a factor here, you can deduce it from the equation, and you will still get the same warning.

In my case, a colleague, he said that he needed to implement both a base class and an interface, because it was an event-based interface.

Ok, then tell your colleague to find out what he wants. If you redefine the interface, then any DoSomething call, whether using a typed Debug link or IDebug with a link type, should cause overridden behavior. Any other behavior would be unexpected and deeply perplexing.

On the other hand, if you need to preserve the behavior of the orignal base class, if you call DoSomething() via an IDebug typed link, then do not reimplement the interface. What other alternative do you offer?

Does this mean that you should know which interfaces the base class implements? Yes of course. I find your question about why anyone should know which interfaces of any given class you intend to inherit from tools that are deeply concerned, to be honest.

+1
source

If you use an Explicit implementation, then the method does not appear in your class without using an interface. You will not be able to call

 new ExternalClass().GetImportantInfo() 

but you can call

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

Due to the explicit implementation, the new keyword is not required. You can even add both implementations to the same class:

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

In addition, the Debug class should not inherit the IDebug interface, since it inherits the ExternalClass. Resharper will show you this as redundant.

0
source

Source: https://habr.com/ru/post/1269152/


All Articles