- Why do we need to implement EIMI?
- How to use EIMI to improve compile-time safety in legacy code.
- EIMI doesn’t always work.
Sometimes when we have legacy code we are not allowed to change inherited interface to its generic version. In this case as we can see from the first example when we pass argument to the method we will get boxing and after that run-time error.
Example 1:
struct MyValueType : IComparable
{
private int m_x;
public MyValueType(int x)
{
m_x = x;
}
public int CompareTo(Object other)
{
return (m_x – (int)other);
}
}
static void Main(string[] args)
{
MyValueType vt = new MyValueType();
Object obj = new Object();
vt.CompareTo(obj); //boxing and runtime-error
}
Example 2:
struct MyValueType : IComparable, IComparable<MyValueType>
{
private int m_x;
public MyValueType(int x)
{
m_x = x;
}
public int CompareTo(MyValueType other)
{
return (m_x – other.m_x);
}
int IComparable.CompareTo(Object other)
{
return (m_x – ((MyValueType)other).m_x);
}
}
We can avoid boxing and the lack of type-safety by using EIMI, we must implement this interface method explicitly and add a new method which will be called in our code.
Example 3:
static void Main(string[] args)
{
MyValueType vt = new MyValueType();
IComparable cmp = (IComparable)vt; //boxing
Object obj = new Object();
cmp.CompareTo(obj); //boxing and runtime-error
}
But if in our code we cast an interface to its non-generic version we will get 2 boxing operations and run-time error again! The first one boxing is when we cast our interface to its non – generic version.