我可以使用显式运算符来创建派生类吗?
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
}
}
无法将“ConsoleApplication1.Derived2”类型的对象转换为“ConsoleApplication1.Derived1”类型。
为什么?我的运算符转换出了什么问题?
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'.
Why? What is wrong with my operator conversion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
问题是您的自定义转换没有被使用,因为
bd2
的编译时类型是Base
,而不是Derived2
。编译器甚至没有考虑您的自定义转换,因此它只是包含正常的转换 - 由于显而易见的原因而失败。 (我假设您了解这种失败,否则您不会首先创建自定义转换。)编译器根据操作数的编译时类型选择运算符和转换。
虽然您可以首先转换为
Derived2
或更改bd2
的声明,但我个人会完全改变策略,并再次查看更大的图景。你想做什么,为什么?例如,Base
中的虚拟方法是否更有意义?The trouble is that your custom conversion isn't being used, because the compile-time type of
bd2
isBase
, notDerived2
. The compiler isn't even considering your custom conversion, so it's just including a normal cast - which is failing for the obvious reason. (I assume you understand that failure, otherwise you wouldn't have created the custom conversion to start with.)Operators and conversions are chosen by the compiler based on the compile-time types of the operands.
While you could cast to
Derived2
first or change the declaration ofbd2
, I would personally change tack completely, and look at the bigger picture again. What are you trying to do, and why? Would a virtual method inBase
make more sense, for example?您只能在层次结构中上下转换类,而不能跨层次转换。
You can only cast classes up and down the hierarchy, not across.
查看操作员的签名:
注意它是静态。您所看到的与方法重载解析的限制类似。
这本质上与下面输出“Object”而不是“String”的原因相同:
也就是说,编译器需要在编译时选择重载。在从
Base
转换为Derived1
的情况下,正确的签名不会发生重载,因此它会尝试实际的向下转换。正如其他人提到的,将bd2
声明为Derived2
可以通过允许编译器选择自定义转换来“修复”此问题。Look at the signature of your operator:
Notice it's static. What you're seeing is similar to the limitation of method overload resolution.
It's essentially the same reason the below outputs "Object" instead of "String":
That is, the compiler needs to pick an overload at compile-time. In the case of casting from a
Base
to aDerived1
, there is no overload with the proper signature, so it attempts an actual downcast. Declaringbd2
asDerived2
, as others have mentioned, would "fix" this by enabling the compiler to select your custom conversion.类 Derived2 不继承自类 Derived1,这就是失败的原因。
以下内容是有效的:
如果 Derived2 继承自 Derived1,则您的尝试将是有效的。
The class Derived2 does not inherit from the class Derived1, that is why this fails.
The following would be valid:
If Derived2 was to inherit from Derived1, what you tried would be valid.
投射到基类。如果您要创建复杂的类层次结构,请考虑实现接口并进行基于接口的编程。
Cast to the base class. If you're creating a complex class heirarchy, consider implementing interfaces and doing interface based programming.