Explicit Interface Method in C#

When any type is loaded by CLR then all method of the class and all inherited public methods and interfaces implementation methods are added to method table.

For example i have created a class Test which is implementing one interface IFormattable and it has only one method ToString().

public class Test: IFormattable
{
public string ToString(string format, IFormatProvider formatProvider)
{
return "Test";
}
}

When this class will be loaded then method table has entries for all virtual methods of Object class and one entry method of IFormattable and one entry for method ToString of class Test.

When you will call ToString() Method by creating object of Test or By making reference to  IFormattable as

Test obj = new Test();
Console.WriteLine(obj.ToString());
IFormattable i = obj;
Console.WriteLine(i.ToString());

output

Test

Test

return value of both method call will be “Test”.This happens because C# compiler understand ToString of class Test as IFormattable’s ToString because name of function, Signature and return type is same and compiler generates metadata that both entries should refer same method location.

Now i will re-write the same class.

public class Test: IFormattable 
{ 
public string ToString(string format, IFormatProvider formatProvider) 
{ 
return "Test"; 
} 
string IFormattable.ToString(string format, IFormatProvider formatProvider) 
{ 
return "IFormattable"; 
} 
}

when you call this implementation then out put will be

Test

IFormattable

When you prefix method with interface name then it is called explicit interface method  implementation EIMI. Note you can not put any accessibly like public or private to it and there is only one way to access this method using interface variable.

EIMI methods can not be marked virtual so we can not override them because EIMI methods are not actual part of type, this is just method to attach interface to a type.

Why EIMI is required ?

This is actually required in scenario  like you have to implement two interface method having same name and same signature.

Suppose you have two interface with a  method SetStream as given below

public interface IReader
{
void SetStream(Stream stream);
}
public interface IWriter
{
void SetStream(Stream stream);
}

Now you have to make a type by implementing these two interface then how you can do that, Explicit interface is only one option as shown here.

public class TestReader : IReader , IWriter
{
Stream m_readerStream = null;
Stream m_writerStream = null;
void IReader.SetStream(Stream stream)
{
m_readerStream = stream;
}
void IWriter.SetStream(Stream stream)
{
m_writerStream = stream;
}
}

and you can call these methods using interface variable.

IReader r =new TestReadet();

r.SetStream(stream) will set m_readerStream

IWriter w = new TestReader();

w.SetStream(stream) wll set m_writerStream.

We can also improve compile time type safety by using EIMI.

For example take IComparable interface

public interface IComparable 
{
Int32 CompareTo(Object other);
}

By implementing this i am creating a value type here

public struct NewValueType : IComparable
{
private Int32 x;
public NewValueType(Int32 newvalue) { x = newvalue; }
public Int32 CompareTo(Object other)
{
return (x - ((NewValueType)other).x);
}
}

To test this i have written this piece of code

public void TestNewValueType()
{
NewValueType v = new NewValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); // Undesired boxing
n = v.CompareTo(o); // InvalidCastException
}

What will happen when i will call CompareTo with parameter of NewValueType, one boxing of NewValueType to Object is required which is undesirable and when it will call CompareTo with a Object variable then it will compile successfully but in run time it will throw exception of InavalidCastException.

We can avoid these situations using explicit interface methods as given here

public struct NewValueType : IComparable
{
private Int32 x;
public NewValueType(Int32 newvalue) { x = newvalue; }
public Int32 CompareTo(NewValueType other)
{
return (x - other.x);
}
// NOTE: No public/private used on the next line
Int32 IComparable.CompareTo(Object other)
{
return CompareTo((NewValueType)other);
}
}

In new implementation we have removed unwanted boxing and added compile time type safety.

public void TestNewValueType()
{
NewValueType v = new NewValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); // Undesired boxing
n = v.CompareTo(o); // Compile time error
}

Now when you try to call CompareTo with other type it will give you compile time error. Unless you call with object type parameter by IComparable variable.

Leave a Reply

Your email address will not be published. Required fields are marked *