9

鉴于这种类隐式转换操作符:有没有办法在C#中进行动态隐式类型转换?

public class MyDateTime 
{ 
    public static implicit operator MyDateTime(System.Int64 encoded) 
    { 
     return new MyDateTime(encoded); 
    } 

    public MyDateTime(System.Int64 encoded) 
    { 
     _encoded = encoded; 
    } 
    System.Int64 _encoded; 
} 

现在我可以做到以下几点:

long a = 5; 
MyDateTime b = a; 

但不执行以下操作:

long f = 5; 
object g = f; 
MyDateTime h = g; 

这给出了一个编译时间:

不能将类型'object'隐式转换为'MyDateTime'。

对我有意义。

现在我修改了前面的例子如下:

long f = 5; 
object g = f; 
MyDateTime h = (MyDateTime)g; 

编译没有问题。现在我得到一个运行时间InvalidCastException

无法强制类型'System.Int64'类型的对象键入MyDateTime'。

这告诉我,C#隐式转换操作符只在编译时应用,并且在.NET运行时试图动态地将对象转换为另一种类型时不应用。

我的问题:

  1. ,对吗?
  2. 有没有其他方法可以做到这一点?

顺便说一句,充分应用是我使用Delegate.DynamicInvoke()调用一个函数,它接受一个MyDateTime参数,而我传递给DynamicInvoke参数的类型是一个漫长的。

回答

13

,对吗?

是的,是的,你是。要挑剔,你应该说“用户定义的隐式转换”而不是“隐式转换” - 转换(几乎)总是显式的。但是你的演绎过载决议选择在编译时调用而不是在运行时是正确的。

有没有其他方法可以做到这一点?

是的。在C#4中,如果您将“对象”键入为“动态”,那么我们在运行时上再次启动编译器,并重新对操作数执行所有分析,就好像它们的编译时类型是当前运行时类型。正如你可能想象的那样,这并不便宜,但如果你在紧密的循环中做到这一点,我们对于缓存和重新使用结果非常聪明。

+0

出于好奇,操作员在运行时不像行为方式那样行为的原因是什么?给出你的答案,感觉就好像它们仅仅是语法糖,而不是更多。在我看来,如果这些类型的操作符被提升为任何类型的第一类成员(这意味着它们成为继承,覆盖和接口等所有其他面向对象优点的一部分),那么它将使C#更加强大。默认情况下,在运行时使用这些语句意味着对语言的设计和实现有重大改变? – MarioDS 2016-02-19 16:18:25

+1

@MDeSchaepmeester:你说得对,这里有点不友好。例如,将int的设计与小数进行比较。你可以说'Func add = decimal.Add;'但是没有办法为int做同样的事情;你必须说'Func add =(x,y)=> x + y'。如果所有内置类型都被设计为Decimal,那么运行时或编译器可能会选择将它们降低到更基本的操作以达到性能的原因。但是这种一致性实际上是来自于“功能性”思维。 – 2016-02-19 16:38:21

+1

@MDeSchaepmeester:我怀疑当设计类型系统和内置类型的操作时,运行时的原始设计者根本没有想到这种统一的功能抽象。当然,十进制同时也有一个运算符+和一个Add方法。甚至不要让我开始介绍代表平等运作的十几种方法!这真是一团糟。下次你从头开始设计一个框架时,尽早得到这个东西。 – 2016-02-19 16:39:03

-2

我知道这是一个老问题,但在在同样的问题,如果任何人绊倒,这将编译并运行良好:

long f = 5; 
object g = f; 
MyDateTime h = g as MyDateTime; 
+0

获得类似的保护。它可以正常运行,因为它不会抛出'InvalidCastException',然而'h'将是'null',这不是OP想要或期望的。 – MarioDS 2016-02-19 16:20:32

相关问题