I have the following interface (it can be changed, but just to give the idea):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
The problem is with the Merge
operation. I am not able to find a way to ensure that the parameter passed to the method is of the same type that this
. For example have a look at the following implementation:
public class A<T> : IObj<T>
{
public void Merge(IObj<T> other)
{
var casted = other as A<T>;
if (casted == null)
throw new ArgumentException("Incorrect type.");
// do the actual stuff
}
}
Any object implementing the interface will always require to be merged with an instance of the same type. Therefore I need to write this boilerplate code to try casting before I do anything.
Is it possible to ensure this by contract / interface / anything else?
From the @nsinreal solution, I propose you one other level on interface (and an abstract class, to avoid implementing several time the interfaces):
public interface IObj<T>
{
void Merge(IObj<T> other);
}
public interface IObj<T, TImplementor> : IObj<T>
where TImplementor : class, IObj<T, TImplementor>
{
void Merge(TImplementor other);
}
public abstract class AObj<T, TImplementor> : IObj<T, TImplementor>
where TImplementor : class, IObj<T, TImplementor>
{
public abstract void Merge(TImplementor other);
void IObj<T>.Merge(IObj<T> other)
{
var casted = other as TImplementor;
if (casted == null)
throw new ArgumentException("Incorrect type.");
Merge(casted);
}
}
public class A<T> : AObj<T, A<T>>
{
override public void Merge(A<T> other)
{
// do the actual stuff
}
}
public class B<T> : AObj<T, B<T>>
{
override public void Merge(B<T> other)
{
// do the actual stuff
}
}
Now, for a class called SpecificObj<T>
, you have both methods:
void Merge(IObj<T>)
void Merge(SpecificObj<T>)
and you can still use it as an IObj<T>
Still not sure that completely answer to your problem.