无法在通用父基类的接口的显式实现内将子类强制转换为另一个子类

时间:2018-09-24 00:25:44

标签: c# .net-4.7

我有以下代码:

class Program
{
    static void Main(string[] args)
    {
        var first = new A();
        OtherClass.EnjoyLife(new OtherClass(first), OtherClass.Default);

        Console.ReadKey();
    }

    public interface IInterface
    {
        void DoStuff(IInterface obj);
    }


    public abstract class AbstractBaseClass<T> : IInterface where T : AbstractBaseClass<T>
    {
        internal abstract void DoStuff(T obj);

        void IInterface.DoStuff(IInterface obj) => DoStuff((T)obj);
    }

    public class A : AbstractBaseClass<A>
    {
        internal override void DoStuff(A obj)
        {
            Console.WriteLine($"Do {obj}");
        }
    }

    public class B : AbstractBaseClass<B>
    {
        internal override void DoStuff(B obj)
        {
            Console.WriteLine($"Do {obj}");
        }

        public static explicit operator A(B obj) => new A();
    }

    public class OtherClass
    {
        public static readonly OtherClass Default = new OtherClass();
        private IInterface foo;

        private OtherClass()
        {
            this.foo = new B();
        }

        public OtherClass(IInterface bar)
        {
            this.foo = bar;
        }

        public static void EnjoyLife(OtherClass left, OtherClass right)
        {
            left.foo.DoStuff(right.foo);
        }
    }
}

运行它时,在InvalidCastException: 'Unable to cast object of type 'B' to type 'A'.' 上执行DoStuff的显式实现时,抛出AbstractBaseClass<T>。即使在B上实现了从AB的显式转换,为什么会这样?

有趣的是,如果我替换

void IInterface.DoStuff(IInterface obj) => DoStuff((T)obj);

作者

void IInterface.DoStuff(IInterface obj) => DoStuff((T)obj.GetType().GetMethod("op_Explicit").Invoke(null, new[] { obj }));

然后它可以正常工作。但是由于其他原因,我无法解决此问题。 我知道该代码已被规避,但我看不出任何理由使其不起作用。

1 个答案:

答案 0 :(得分:0)

基于Main方法和OtherClass中的内容,当您覆盖DoStuff方法时,应该依赖于抽象,而不是具体的类 例如

internal override void DoStuff(IInterface obj)
{
    Console.WriteLine($"Do {obj}");
}

但是要做类似的事情,您应该删除抽象类上的约束

public abstract class AbstractBaseClass<T> : IInterface// where T : AbstractBaseClass<T>

并在具体类上将T分配给IInterface

public class A : AbstractBaseClass<IInterface>

我认为如果这样对您的抽象类没有帮助,您应该直接实现该接口。

我需要了解更多信息,该设计的目的是什么?因为如果我们知道您要实现的目标,有很多解决方案。