如何在C#中确保对象的类型与此相等?

时间:2016-08-09 10:11:17

标签: c# generics interface type-conversion strong-typing

问题

我有以下界面(可以更改,但只是为了提出想法):

public interface IObj<T>
{
    void Merge(IObj<T> other);
}

问题在于Merge操作。我无法找到确保传递给方法的参数与this的类型相同的方法。例如,看看以下实现:

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
    }
}

实现接口的任何对象始终需要与相同类型的实例合并。因此,我需要编写这个样板代码,以便在我做任何事情之前尝试进行。

问题

是否可以通过合同/界面/其他任何方式确保这一点?

2 个答案:

答案 0 :(得分:5)

您可以尝试使用self-referencing generic pattern。 它经常用于流畅的可继承对象构建器。

对于你的情况,它应该是这样的:

public interface IObj<T, TSelf> where TSelf : IObj<T, TSelf>
{
    void Merge(TSelf other);
}

class A<T>: IObj<T, A<T>> {
    public void Merge(A<T> alreadyCasted) {

    }
}

不幸的是,这也引入了样板代码(在A类声明中)。但是当你在基类的接口中有很多方法时,这很好。

据我所知,没有其他变种。

答案 1 :(得分:2)

从@nsinreal解决方案中,我建议你在接口上使用另一个级别(和一个抽象类,以避免实现几次接口):

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
    }
}

现在,对于名为SpecificObj<T>的类,您有两种方法:

void Merge(IObj<T>)
void Merge(SpecificObj<T>)

您仍然可以将其用作IObj<T>

仍然不确定完全回答你的问题。