Home .NET A little bit about interfaces in .Net (based on one interview)

A little bit about interfaces in .Net (based on one interview)

by admin

Last Monday I was lucky enough to get a job interview for a Senior .Net Developer at an international company.During the interview I was offered to take a test, where a number of questions were related to .Net.In particular in one of the questions I had to give an opinion (true/false) about some statements, among which was this :

In .Net, any array of elements, such as int[], implements an IList by default, which allows you to use it as a collection in a foreach statement.

After quickly answering this question in the negative and separately writing in the margin that foreach requires an implementation of IEnumerable rather than IList, I moved on to the next question. On the way home, however, I was plagued by a question: does the array still implement this interface or not?
About IList, I vaguely remembered that this interface gives me an IEnumerable, an indexer, and a Count property that contains the number of collection elements, as well as a couple other rarely used properties like IsFixedCollection(). The array has a Length property for its size, and Count in IEnumerable is an extension method from LINQ, which would be impossible if this method were implemented in a class. So it turned out that the array could not implement the IList interface, but some vague feeling kept me going. So in the evening after the interview I decided to do some research.

The System class.Array

Since I didn’t have Reflector.Net installed, I just wrote a short C# program to see what kind of interfaces are implemented by an integer array.

var v = new int[] { 1, 2, 3 };var t = v.GetType();var i = t.GetInterfaces();foreach(var tp in i)Console.WriteLine(tp.Name);

Here is the complete list of received interfaces from the console window :

ICloneableIListICollectionIEnumerableIStructuralComparableIStructuralEquatableIList`1ICollection`1IEnumerable`1IReadOnlyList`1IReadOnlyCollection`1

Thus, array in .Net still implements the IList interface and its generalized version IList<>
To get more information I built a diagram of the class System.Array.
A little bit about interfaces in .Net (based on one interview)
My mistake immediately struck me: Count was not a property of IList but of ICollection, the previous interface in the inheritance chain. Nevertheless the array itself didn’t have that property anymore, as well as many other properties of the IList interface, although other properties of that interface, IsFixedSize and IsReadOnly were implemented. How is this even possible?
Everything immediately falls into place when you remember that in C# you can implement interfaces other than
implicitly but also explicitly. I know about it from tutorials that gave an example of such implementation when base class already contains a method with the same name as the interface method. I also saw this possibility in ReSharper. To date, however, I have not directly encountered the need to implement interfaces explicitly in my own projects.

Comparison of explicit and implicit interface implementations

Let’s compare these two types of interface implementations :.

Criteria Implicit implementation Explicit implementation
Basic syntax
interface ITest{void DoTest();}public class ImplicitTest : ITest{public void DoTest(){ }}

interface ITest{void DoTest();}public class ExplicitTest : ITest{void ITest.DoTest(){ }}

Visibility Implicit implementation is always public, so methods and properties can be directly accessed.

var imp = new ImplicitTest();imp.DoTest();

Explicit implementation is always closed (private).
To access implementation you have to cast an instance of a class to an interface (upcast to interface).

var exp = new ExplicitTest();((ITest)exp).DoTest();

Polymorphy Implicit implementation of an interface can be virtual, allowing this implementation to be rewritten in descendant classes. Explicit implementation is always static. It cannot be overwritten (override) or overlapped (new) in descendant classes. Footnote 1
Abstract class and implementation An implicit implementation can be abstract and implemented only in a descendant class. An explicit implementation cannot be abstract, but the class itself can have other abstract methods and be abstract itself. Footnote 2

Notes :
Footnote 1 – As rightly observes mayorovp in the comments, the implementation can be overridden by reimplementing the interface explicitly in the descendant class (see the first comment of the article).
Footnote 2 – In One of the blogs pointed out that the class itself cannot be abstract. Perhaps this was true for some previous version of the compiler, in my experiments I had no problem implementing the interface explicitly in an abstract class.

Why interfaces need to be implemented explicitly

Explicit interface implementation according to MSDN , is required when multiple interfaces implemented by a class have a method with the same signature. This problem is generally known in the English-speaking world by the blood-curdling name "deadly diamond of death" which translates into Russian as "problem of the rhombus" Here is an example of such a situation :

/* Listing 1 */interface IJogger{void Run();}interface ISkier{void Run();}public class Athlete: ISkier, IJogger{public void Run(){Console.WriteLine("Am I an Athlete, Skier or Jogger?");}}

By the way, this example is correct code in C#, i.e. it (correctly) compiles and runs, and the Run() method is both a method of the class itself and an implementation of as many as two interfaces. So, we can have one implementation for different interfaces and for the class itself. You can check this by the following code :

/* Listing 2 */var sp = new Athlete();sp.Run();(sp as ISkier).Run();(sp as IJogger).Run();

The result of executing this code is "Am I an Athlete, Skier or Jogger?" , displayed in the console three times.
This is where we can use the explicit implementation of the interface to separate all three cases :

/* Listing 3 */public class Sportsman{public virtual void Run(){Console.WriteLine("I am a Sportsman");}}public class Athlete: Sportsman, ISkier, IJogger{public override void Run(){Console.WriteLine("I am an Athlete");}void ISkier.Run(){Console.WriteLine("I am a Skier");}void IJogger.Run(){Console.WriteLine("I am a Jogger");}}

In this case, when the code from Listing 2 is executed, we will see three lines in the console, "I am an Athlete" , "I am a Skier" and "I am a Jogger"

Pros and cons of different interface implementations

Implementation visibility and selective implementation

As shown above, an implicit implementation is syntactically the same as a normal class method (and if this method was already defined in the ancestor class, then in this syntax the method will be hidden in the descendant and the code will compile with compiler warning about hiding the method without any problems). Furthermore, it is possible to selectively implement individual methods of the same interface both explicitly and implicitly :

/* Listing 4 */public class Code{public void Run(){Console.WriteLine("I am a class method");}}interface ICommand{void Run();void Execute();}public class CodeCommand : Code, ICommand{// implicit interface method implementation// => public implementation// implicit base class method hiding (warning here)public void Run(){base.Run();}// explicit interface method implementation// => private implementationvoid ICommand.Execute(){}}

This allows you to use implementations of individual interface methods as native methods of the class and they are available, for example, through IntelliSense, as opposed to explicit implementations of methods that are private and only visible after cast to the corresponding interface.
On the other hand, the ability to privately implement methods allows you to hide a number of interface methods while still fully implementing them. Going back to our very first example with arrays in .Net, we can see that the array hides, for example, the Count property of the ICollection interface, exposing that property as Length (probably an attempt to maintain compatibility with C++ STL and Java). This way we can hide certain methods of the implemented interface and not hide (=make public) others.
The problem here, however, is that in many cases it is completely impossible to guess which interfaces are implemented "implicitly" by a class, because neither methods nor properties of those interfaces are visible in IntelliSense (the example with System.Array is also illustrative here). The only way to detect such implementations is to use reflection, for example with the Object Browser in Visual Studio.

Interface refactoring

As the implicit (public) implementation of an interface is not different from the public method implementation of a class, if you refactor an interface and remove any public method from it (e.g., merging Run() and Execute() methods from the above ICommand interface into a single Run() method), all implicit implementations will leave an open access method, which very likely will have to be maintained even after refactoring, as this public method may already have different dependencies in other system components. This will violate the principle of programming "against interfaces, not implementations", since dependencies will already be between specific (and probably different in different classes) implementations of the former interface method.

/* Listing 5 */interface IFingers{void Thumb();void IndexFinger();// an obsolete interface method// void MiddleFinger();}public class HumanPalm : IFingers{public void Thumb() {}public void IndexFinger() {}// here is a "dangling" public methodpublic void MiddleFinger() {}}public class AntropoidHand : IFingers{void IFingers.Thumb() {}void IFingers.IndexFinger() {}// here the compiler errorvoid IFingers.MiddleFinger() {}}

In the case of private implementations of interfaces, all classes with explicit implementations of a method that no longer exists will simply stop compiling, but after removing the implementation that has become unnecessary (or refactoring it into a new method) we will have no "extra" public method that is not bound to any interface. Of course, dependencies on the interface itself may need to be refactored, but here at least there will be no violation of the "program to interfaces, not implementations" principle.
As for properties, the implicitly implemented interface properties (properties) allow you to access them via methods-accessors (getter and setter) both externally and directly from the class itself, which can lead to unnecessary effects (for example, unnecessary data validation during properties initialization).

/* Listing 6 */interface IProperty{int Amount { get; set; }}public class ClassWithProperty : IProperty{// implicit implementation, publicpublic int Amount { get; set; }public ClassWithProperty(){// internal invocation of the public setterAmount = 1000;}}public class ClassWithExplicitProperty : IProperty{// explicit implementation, privateint IProperty.Amount { get; set; }public ClassWithExplicitProperty(){// internal invocation isn't possible// compiler error hereAmount = 1000;}}

With explicit implementation of interface properties these properties remain private and for access, one has to go the "long" way and declare an additional private field through which the initialization occurs. This results in cleaner code when methods to access the property are only used for external access.

Using explicit typing of local variables and class fields

In case of explicit implementation of interfaces, we have to explicitly specify that we are not working with an instance of the class, but with an instance of the interface. So, for example, it becomes impossible to use type inference and declaration of local variables in C# with var. Instead we have to use explicit declaration specifying interface type when declaring local variables, as well as in method signatures and class fields.
So, on the one hand we kind of make the code a bit less flexible (e.g. ReSharper by default always suggests using a declaration with var if possible), but we avoid potential problems with being tied to a specific implementation as the system and its code size grows. This point may seem controversial to many people, but in case you have several people working on the project in different corners of the world, using explicit typing can be very useful, since it improves readability and reduces maintenance costs.
Sources on the subject This article was prepared using information from a number of online sources, particularly blogs ( [1] , [2] , [3] and [4] ), as well as from [5] and [6] StackOverflow questions, A very interesting article on CodeProject and chapter 13.5 of Jeffrey Richter’s " CLR via C# ".
A little bonus: two questions (for the inquisitive) These questions have no direct relation to the subject of explicit implementation of interfaces, but I think they might be of interest to someone here:
1. If we add another line to Listing 2

(sp as Sportsman).Run();

What will be displayed in the console?
2. How with a minimal change in Listing 3 (replacing one keyword with another) to get the phrase output to the console "I am a Sportsman" in the first question?

You may also like