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'.
为什么呢?我的运营商转换有什么问题?
答案 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)
转换为基类。如果要创建复杂的类层次结构,请考虑实现接口并执行基于接口的编程。