我可以使用显式运算符来创建派生类吗?

时间:2011-02-08 15:05:41

标签: c# .net inheritance explicit

class Base
{
}

class Derived1 : Base
{
}

class Derived2 : Base
{
    public static explicit operator Derived1(Derived2 d2)
    {
        return new Derived1();
    }
}

class Test
{
    static void Main()
    {
        Base bd2 = new Derived2();

        Derived1 d2ConvertedD1 = (Derived1)bd2; //throws InvalidCastException

    }
}
  

Unable to cast object of type 'ConsoleApplication1.Derived2' to type 'ConsoleApplication1.Derived1'.

为什么呢?我的运营商转换有什么问题?

5 个答案:

答案 0 :(得分:10)

问题是您的自定义转换没有被使用,因为bd2的编译时类型是Base,而不是Derived2。编译器甚至没有考虑你的自定义转换,所以它只包括一个正常的转换 - 由于显而易见的原因而失败。 (我假设你理解失败,否则你不会创建自定义转换开始。)

编译器根据操作数的编译时类型选择运算符和转换。

当你可以首先投放到Derived2或更改bd2的声明时,我会亲自改变策略,再看一下大局。你想做什么,为什么?例如,Base中的虚拟方法会更有意义吗?

答案 1 :(得分:5)

您只能在层次结构中上下编译类,而不能跨越。

答案 2 :(得分:1)

查看运营商的签名:

public static explicit operator Derived1(Derived2 d2);

注意它是静态。您所看到的与方法重载分辨率的限制类似。

这与下面输出“Object”而不是“String”的原因基本相同:

static void WriteObject(object obj) { Console.WriteLine("Object"); }
static void WriteObject(string str) { Console.WriteLine("String"); }

object obj = "I am a string.";
WriteObject(obj);

也就是说,编译器需要在编译时选择一个重载。在从Base转换为Derived1的情况下,没有适当签名的重载,因此它会尝试实际向下转换。正如其他人所提到的那样,将bd2声明为Derived2会通过启用编译器选择自定义转换来“修复”此问题。

答案 3 :(得分:0)

类Derived2不继承Derived1类,这就是失败的原因。

以下内容有效:

  

Base d2ConvertedBase =(Base)bd2;

如果Derived2是从Derived1继承的,那么您尝试的将是有效的。

答案 4 :(得分:0)

转换为基类。如果要创建复杂的类层次结构,请考虑实现接口并执行基于接口的编程。