我有这个功能:
static void Func1<T>(T x, T y)
{
dynamic result = ((dynamic)x + y); //line 1
dynamic result2 = (x + y); //line 2
}
此func可以Func(1,2);
执行但是,第1行 OK ,而第2行 BANG (在编译时)。
第2行引发的异常是:
运算符'+'不能应用于'T'和'T'类型的操作数
因此,我们需要创建一个运算符重载。好的,到目前为止一切顺利。
但是第1行呢?它不应该在y
((dynamic)x + (dynamic)y);
我知道它正在运行时进行评估,但是为什么C#编译器接受第1行中的+
运算符(即错误地假设T可以+
为其他东西)?
答案 0 :(得分:7)
在您的第一个示例中,通过使x
成为dynamic
,您实际上也使operator+
操作动态化。这消除了T
的类型说明符x
,从而消除了T
无效operator+
的投诉。
在运行时动态绑定将发生并评估两个操作数以确保可以使用operator+
:
如果算术运算符的操作数具有编译时类型dynamic,则表达式是动态绑定的(第7.2.2节)。在这种情况下,表达式的编译时类型是动态的,下面描述的解析将在运行时使用具有编译时类型动态的那些操作数的运行时类型进行。
在第二个示例中,编译器知道x + y
的类型,只是将结果存储到dynamic
变量中。 result2
的进一步用法将动态绑定。这是有道理的,因为赋值运算符的 right 没有动态操作:
当不涉及动态表达式时,C#默认为静态绑定,这意味着在选择过程中使用组成表达式的编译时类型。
答案 1 :(得分:3)
dynamic
基本上告诉编制者&#34;不要试图确保我所做的事情是合法的;我确定它会在运行时&#34;。您在动态类型变量上尝试的任何操作都将编译。如果分配给动态变量的类型实际上没有实现该操作,它就不会成功运行。
至于为什么它们都不必是动态的,编译器基本上会尝试在与签名匹配的操作中涉及的任一类型上找到一个运算符(静态方法),从LValue开始。在LValue是动态的情况下,编译器必须假设操作存在于将用作X的任何内容上,即使X与Y具有相同的占位符类型,并且不知道Y具有+运算符。