Intended purpose of hiding a base class' explicit interface implementation without warning? - c#

Imagine these specifications are from an external 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:
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 Debugclass, without implementing the method:
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. But using the new keyword to overwrite an explicitly implemented method gives a compile warning:
The member 'Program.Debug.GetImportantInfo()' does not hide an inherited member. The new keyword is not required.
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? 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.
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.
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. 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. 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.
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. Resharper will show you this as redundant.

Related

Calling C# interface default method from implementing class

C# 8 supports default method implementations in interfaces. My idea was to inject a logging method into classes like this:
public interface ILoggable {
void Log(string message) => DoSomethingWith(message);
}
public class MyClass : ILoggable {
void MyMethod() {
Log("Using injected logging"); // COMPILER ERROR
}
}
I get a compiler error: "The name does not exist in the current context"
Is it impossible to use default method implementations in this way?
EDIT:
For the correct response regarding C# rules, see the accepted answer. For a more concise solution (the original idea of my question!) see my own answer below.
See the documentation at https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-members-versions
That cast from SampleCustomer to ICustomer is necessary. The SampleCustomer class doesn't need to provide an implementation for ComputeLoyaltyDiscount; that's provided by the ICustomer interface. However, the SampleCustomer class doesn't inherit members from its interfaces. That rule hasn't changed. In order to call any method declared and implemented in the interface, the variable must be the type of the interface, ICustomer in this example.
So the method is something like
public class MyClass : ILoggable {
void MyMethod() {
ILoggable loggable = this;
loggable.Log("Using injected logging");
}
}
If you want to avoid clutter and repetitive casting you can add a single property which casts the type as the interface:
public class MyClass : ILoggable
{
ILoggable AsILoggable => (ILoggable)this;
void MyMethod()
{
AsILoggable.Log("Using injected logging");
}
}
But this is off. It seems wrong, regardless of how it's done. From the documentation:
The most common scenario is to safely add members to an interface already released and used by innumerable clients.
When there was some concern about having implementations in interfaces - which previously had none - this was the sentence that made sense of it. It's a way to add to an interface without breaking classes that already implement it.
But this question implies that we are modifying the class to reflect a change to an interface it implements. It's the exact opposite of the stated use case for this language feature.
If we're already modifying the class, why not just implement the method?
public void Log(string message) => DoSomethingWith(message);
When we add a default interface implementation, we provide an implementation to consumers of the interface - classes that depend on an abstraction.
If we depend on the default interface implementation from within the class that implements the interface, then a change to the interface becomes, in effect, a change to the internal implementation of the class. That's not what an interface is for. An interface represents external-facing behavior, not internal implementation.
It's as if the class is stepping outside of itself, looking back in at itself as an external consumer, and using that as part of its internal implementation. The class doesn't implement the interface, but it depends on it. That's weird.
I won't go so far as to say that it's wrong, but it feels like an abuse of the feature.
In CLR all interface member implementations are explicit, so in your code Log will be available in instances of ILoggable only, like it's recommended to do here:
((ILoggable)this).Log("Using injected logging")
The problem with the answers that cast the class to an interface is that it may or may not call the default interface method, depending on whether or not the class has implemented a method to override the default method.
So this code:
((ILoggable)this).Log(...)
ends up calling the default interface method, but only if there is no interface method defined in the class that overrides the default method.
If there is a method in the class that overrides the default method, then that is the method that will be called. This is usually the desired behavior. But, if you always want to call the default method, regardless of whether or not the implementing class has implemented its own version of that interface method, then you have a couple of options. One way is to:
Declare the default method as static. Don't worry, you will still be able to override it in a class that inherits from it.
Call the default method using the same type of syntax when calling a static method of a class, only substitute the interface name for the class name.
See this answer for a code example, along with an alternative way of calling a default interface method.
From reading an article about these default methods, I think you should try to upcast it to the interface:
((ILoggable)this).Log("Using injected logging")
I haven't checked it, just my thought according to this article.
Here are two alternative solutions to the ones already suggested:
First is to simply implement the interface method:
public class MyClass : ILoggable {
void MyMethod() {
Log("Using injected logging");
}
public void Log(string message) => ((ILog)this).Log(message);
}
This allows the method to be called directly, without having to write the cast to ILog each time.
Things to note:
this will make the method available on MyClass to outside users of it as well, where previously it was only available when an instance of MyClass is cast to / used as ILog
if you want to use 10 different methods from ILog in your class, you probably don't want to implement them all.
on the flipside, there are many scenarios where this is the "natural" / intended approach, primarily when MyClass extends the interface method with some custom logic (like ((ILog)this).Log("(MyClass): " + message) )
Second is using extension methods:
public static class LogExtensions
{
public static void Log<T>(this T logger, string message) where T : ILoggable => logger.Log(message);
}
public class MyClass : ILoggable {
void MyMethod() {
this.Log("Using injected logging");
}
}
This might be useful when ILoggable contains many methods / is implemented in many classes.
this still allows for Log to be overwritten in MyClass and the override to be called
essentially just syntactic sugar, shortening ((ILoggable)this) to this
The accepted answer and the other responses are correct.
However, what I wanted is a concise call of the Log method.
I achieved that with an extension method on the ILoggable interface:
public static class ILoggableUtils { // For extension methods on ILoggable
public static void Log(this ILoggable instance, string message) {
DoSomethingWith(message, instance.SomePropertyOfILoggable);
}
}
In this way, I can at least call this.Log(...); in my class instead of the ugly ((ILoggable)this).Log(...).
My solution is adding new abstract class between interface and it's implementations:
public interface ILoggable {
void Log(string message);
void SomeOtherInterfaceMethod();
}
public abstract class Loggable : ILoggable {
void Log(string message) => DoSomethingWith(message);
public abstract void SomeOtherInterfaceMethod(); // Still not implemented
}
public class MyClass : Loggable {
void MyMethod() {
Log("Using injected logging"); // No ERROR
}
public override void SomeOtherInterfaceMethod(){ // override modifier needed
// implementation
};
}

C# Using generics and interface implementation

Context: .NET 4.0, C#
I'm creating a set of interfaces and a set of clases that implement them to provide some service. The clients use the concrete clases but call methods that are declared using the interfaces as parameter types.
A simplified example is this one:
namespace TestGenerics
{
// Interface, of fields
interface IField
{
}
// Interface: Forms (contains fields)
interface IForm<T> where T : IField
{
}
// CONCRETE CLASES
class Field : IField
{
}
class Form <T> : IForm<T> where T : IField
{
}
// TEST PROGRAM
class Program
{
// THIS IS THE SIGNATURE OF THE METHOD I WANT TO CALL
// parameters are causing the error.
public static void TestMethod(IForm<IField> form)
{
int i = 1;
i = i * 5;
}
static void Main(string[] args)
{
Form<Field> b = new Form<Field>();
Program.TestMethod(b);
}
}
}
The code makes sense to me, but I get the compiler error:
Argument 1:
cannot convert from 'TestGenerics.Form<TestGenerics.Field>' to
'TestGenerics.IForm<TestGenerics.IField>' TestGenerics
I'm not sure what I'm doing wrong, I've read lots of pages on the internet but none solved my problem.
Is there a solution that would not modify that much the architecture of what I'm trying to build:
Edit:I designed the interfaces in a way such that they should be independent of concrete clases that implement them. The concrete clases could be loaded from a dll, but most of the application Works with the interfaces. In some cases I need to use concrete clases, specially when using clases that need to be serialized.
Thanks in advance.
Alejandro
The problem is that Form<Field> implements IForm<Field> but not IForm<IField>. You cannot use an inherited class (or interface) as a generic parameter unless it is marked as covariant with the out identifier. However, marking your interface as covariant will restrict the usage significantly (basically making in an "output-only" interface like IEnumerable) so it may not work for you.
One way to get it to work is to make TestMethod generic as well:
public static void TestMethod<T>(IForm<T> form) where T:IField
{
int i = 1;
i = i * 5;
}
You can use Covariance, like so:
interface IForm<out T> where T : IField
{
}
More about Covariance and Contravariance here.
Others have pointed out the reasoning behind the error message, but let's examine the design of your sample code for a moment. Perhaps you're using a generic where none is needed.
You've already said you're using methods declared in the IField interface, so there may be no need to make your IForm class generic - simply have it store references to IField, instead of the generic argument 'T' (which is already guaranteed to be an IField anyway).
For instance, use:
public interface IForm
{
IEnumerable<IField> Fields { get; set; }
}
instead of
public interface IForm<T> where T : IField
{
IEnumerable<T> Fields { get; set; }
}

Ignoring Interface method implementation in C#

Suppose an Interface I has two methods. For example Method1() and Method2().
A class A Implements an Interface I.
Is it possible for class A to implement only Method1() and ignore Method2()?
I know as per rule class A has to write implementation of both methods. I am asking if there any way to violate this rule?
You can avoid implementing it (a valid scenario) but not ignore it altogether (a questionable scenario).
public interface IFoo
{
void A();
void B();
}
// This abstract class doesn't know what to do with B(), so it puts
// the onus on subclasses to perform the implementation.
public abstract class Bar : IFoo
{
public void A() { }
public abstract void B();
}
No, there's no such concept in C# of optional interface members. If A implements I, then it must provide some implementation for all of I's members, even if the implementation does nothing or only throws an exception.
public class A : I
{
public void Method1()
{
// Do nothing.
}
public void Method2()
{
throw new NotImplementedException();
}
}
From a design perspective, why would you want to do this anyway in a statically typed language? Furthermore, why not just have two interfaces?
public interface I1 { void Method1(); }
public interface I2 { void Method2(); }
With your interfaces coded like this, you can have classes that implement one interface or the other, or both, or neither. To me, this makes more sense anyway.
UPDATE 2018-06-13
The C# lang Git Hub has a proposal in progress for default interface methods. In short, the interface developer would be able to provide an implementation for a method or methods in the interface itself, and the developer using the interface on their class or struct would not have to implement those methods explicitly. Not exactly what the OP was asking about, but potentially useful.
You must implement all methods of the interfaces your class inherits from. There is no way around that. But you can use explicit interface implementation to hide the method.
That way a user doesn't see the method on a variable that has the class as type, but when he casts to the interface he can call the method.
class A : I
{
void I.Method2()
{
throw new NotSupportedException();
}
}
then
A a;
a.Method2(); //doesn't compile
I i = a;
i.Method2(); //works
If the class A is only an abstract base class, you can also use an abstract method to implement the interface, leaving the concrete implementation to the derived classes.
No, there's not.
But you can code :
public void Method2(){
throw new NotImplementedException();
}
That will inform the application that this method cannot be called from this instance.
Yes if I was a class, but No if it's an interface.

Returning more derived classes than interface specifies

I'm trying to create a set of classes with different level of abstraction. I will use the Vector example here.
My goal is that the user of my classes can choose the level of abstraction to use i.e. they may or may not want to be using the more derived class.
interface IVector
{
Vector A();
}
interface ISparseVector : IVector
{
new SparseVector A();
}
Now, I implement the classes as such:
class Vector : IVector
{
public Vector A() { return new Vector(); }
}
class SparseVector : Vector,ISparseVector
{
public new SparseVector A() { return new SparseVector(); }
}
This is all fine and dandy. However, when the base class is abstract such as:
abstract class Vector : IVector
{
public abstract Vector A();
}
class SparseVector : Vector,ISparseVector
{
public SparseVector A() { return new SparseVector(); } // Hides abstract member.
}
I get a compile error saying that the derived method is hiding the abstract method in Vector. Any idea of how to get around this?
The feature you want is called "return type covariance", and it is not a feature of C#. Return type covariance is the feature where you can have a virtual method that return an Animal, and then you override that with a method that returns a Giraffe.
Doing so is typesafe and some languages do have this feature -- C++ for example -- but C# does not and we have no plans to add it. Your overriding method has to be marked override, and it has to match exactly -- in name, formal parameter types, and return type.
The reason is in your first example on the Vector class, you weren't specifying an access level for the A() method. This means it is a private method, which is the default. You could use the new keyword in the SparseVector class to get around this error.
For a start, you should look at this thread which specifies why you cannot have an abstract constructor.
Why can't I create an abstract constructor on an abstract C# class?
Then, you should put an abstract method in your Vector class that can actually be overridden to provide implementation, as abstract methods are supposed to be.
You can't mix abstract and interface methods the way you're trying. If you were to declare 'Vector' abstract and override the implementation of A(), you'd be overriding 'Vector A()' from your abstract class, but that wouldn't implement the interface ISparseVector.Vector, which has a return type of ISparseVector.
Your use-case doesn't appear to require that 'Vector' be abstract.

Compiler says I am not implementing my interface, but I am?

Okay, I have two namespaces. One contains my interface and one contains the implementing class. Like this:
namespace Project.DataAccess.Interfaces
{
public interface IAccount
{
string SomeMethod();
}
}
namespace Project.DataAccess.Concrete
{
class Account : Project.DataAccess.Interfaces.IAccount
{
string SomeMethod()
{
return "Test";
}
}
}
With this code I get an error:
'Project.DataAccess.Concrete.Account' does not implement interface member 'Project.DataAccess.Interfaces.IAccount.SomeMethod'. 'Project.DataAccess.Concrete.Account.SomeMethod' cannot implement an interface member because it is not public
If I make the class and method public it works fine. But if I instead qualify the method name with the interface name, that fixes it too. Why? Ex:
namespace Project.DataAccess.Concrete
{
class Account : Project.DataAccess.Interfaces.IAccount
{
string IAccount.SomeMethod()
{
return "Test";
}
}
}
Why does this fix it? And why does it have to be public if I don't do that?
To be clear
I am well aware that making it public fixes it. Making the method signature look like this WITHOUT making anything public fixes it:
string IAccount.SomeMethod()
Why?
Interface implementations need to be public or explicit:
Public:
class Account : IAccount
{
public string SomeMethod()
{
return "Test";
}
}
Explicit:
class Account : IAccount
{
string IAccount.SomeMethod()
{
return "Test";
}
}
The default access modifier in C# is private if you do not specify the access modifier.
You have 2 basic options when implementing intefaces: implicit or explicit. Implicit implementation takes on the form of a public method or property, while explicit is in the form of a method or property prefaced with the IFoo. modifier that is otherwise not public.
interface IFoo
{
void Bar();
}
class FooA : IFoo
{
public void Bar() { }
}
class FooB : IFoo
{
void IFoo.Bar() { }
}
The difference here is that in the case of FooA, void Bar is part of the publicly visible API of the class. Code can call Bar via the instance of the class.
FooA foo = new FooA();
foo.Bar(); // legal
In the case of FooB, void Bar is not part of the publicly visible API of the class. The method can still be called, but it must explicitly be called via the interface.
FooB foo = new FooB();
foo.Bar(); // not legal
IFoo myFoo = foo;
myFoo.Bar(); // legal
Your code does not compile because it walks in the uncharted waters between an implicit and explicit interface implementation. You saw that with your change, you had legally defined an explicit implementation, which is why that particular version compiles. Otherwise, you've also found that the public modifer is needed to make the non-explicit version compile.
Methods implementing interface needs to be public. In your later case, you are declaring it explicitly. This is what specification says about explicit interface implementation.
Explicit interface member
implementations have different
accessibility characteristics than
other members. Because explicit
interface member implementations are
never accessible through their fully
qualified name in a method invocation
or a property access, they are in a
sense private. However, since they can
be accessed through an interface
instance, they are in a sense also
public.
'Project.DataAccess.Concrete.Account.SomeMethod' cannot implement an interface member because it is not public
namespace Project.DataAccess.Concrete
{
public class Account : IAccount
{
public string IAccount.SomeMethod()
{
return "Test";
}
}
}
You're not mentioning in your class declaration that you'll be implementing IAccount.
Your class declaration should look like this:
class Account : IAccount
{
//Implementation here.
}
Also, what's happening is that you're using the "default" protection level for Account, and that protection level isn't "public", but an Interface (IAccount) defines public methods by default.
So, when you preface both the Class and Method names with public you're actually implementing the interface. Likewise, when you declare SomeMethod as
IAccount.SomeMethod()
{
//Implementation Here
}
what you're doing is Explicitly Implementing the interface.
I think declaring it explicitly with string IAccount.SomeMethod() works because .NET knows that this implementation of the method can only be accessed through the interface, and so it carries over the public visibility from the interface. In other words, since you are explicitly saying it is an interface member, the compiler can imply that it has to be public, so you don't have to re-state the obvious.
This is also discussed here: http://msdn.microsoft.com/en-us/library/aa664591%28v=vs.71%29.aspx
It is a compile-time error for an
explicit interface member
implementation to include access
modifiers, and it is a compile-time
error to include the modifiers
abstract, virtual, override, or
static.
Explicit interface member
implementations have different
accessibility characteristics than
other members. Because explicit
interface member implementations are
never accessible through their fully
qualified name in a method invocation
or a property access, they are in a
sense private. However, since they can
be accessed through an interface
instance, they are in a sense also
public.
class Account : IAccount
{
public string SomeMethod()
{
return "Test";
}
}
Tell your class to implement the interface. Using the Interface.Method name explicitly implements the method (but i'm not sure why or how) and you need to make them public.
You want to use Interface.Method to explicitly implement an interface requirement when the class already has a member of the same name
class MyClass : IAccount
{
public int SomeMethod() {}
public string IAccount.SomeMethod() {}
}

Categories