2
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'.

为什么?我的运算符转换有什么问题?

4

5 回答 5

10

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

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

虽然你可以投到Derived2first 或更改 的声明bd2,但我个人会完全改变策略,然后再看大局。你想做什么,为什么?例如,虚拟方法Base是否更有意义?

于 2011-02-08T15:09:35.310 回答
5

您只能在层次结构上下转换类,而不能跨越。

于 2011-02-08T15:07:52.667 回答
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);

也就是说,编译器需要在编译时选择一个重载。在从 a 转换为 a 的情况下,Base正确Derived1的签名没有重载,因此它尝试进行实际的向下转换。正如其他人所提到的,声明bd2Derived2将通过使编译器选择您的自定义转换来“解决”此问题。

于 2011-02-08T15:15:13.570 回答
0

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

以下将是有效的:

基础 d2ConvertedBase = (基础) bd2;

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

于 2011-02-08T15:09:04.007 回答
0

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

于 2011-02-08T15:09:45.503 回答