8

我有这个功能:

static void Func1<T>(T x, T y)
{
    dynamic result = ((dynamic)x + y); //line 1
    dynamic result2 = (x + y);         //line 2
}

此函数可以执行为Func(1,2);但是,第 1 行是OK,而第 2 行是BANG(在编译时)。

第 2 行抛出的异常是:

运算符“+”不能应用于“T”和“T”类型的操作数

所以,我们需要创建一个运算符重载。好的,到目前为止一切顺利。

但是第 1 行呢?它不应该也需要动态演员表y吗?

((dynamic)x + (dynamic)y);

我知道它是在运行时评估的,但为什么 C# 编译器接受第+1 行中的运算符(即错误地假设 T 可以是+其他东西)?

4

2 回答 2

7

在您的第一个示例中,通过制作xadynamic您实际上也使operator+操作动态化。这摆脱了类型说明符Tfor x,从而摆脱了T无效的抱怨operator+

在运行时会发生动态绑定并评估两个操作数以确保operator+可以使用:

如果算术运算符的操作数具有编译时类型动态,则表达式是动态绑定的(第 7.2.2 节)。在这种情况下,表达式的编译时类型是动态的,下面描述的解析将在运行时使用那些具有编译时类型动态的操作数的运行时类型进行。

在您的第二个示例中,编译器知道类型,x + y并且只是将结果存储到dynamic变量中。的进一步使用result2将被动态绑定。这是有道理的,因为赋值运算符的右侧没有动态操作:

当不涉及动态表达式时,C# 默认为静态绑定,这意味着在选择过程中使用构成表达式的编译时类型。

于 2012-05-04T16:57:20.473 回答
3

dynamic基本上告诉编译器“不要试图确保我正在做的事情是合法的;我确信它会在运行时”。您尝试对动态类型变量的任何操作都将编译。如果分配给动态变量的类型实际上没有实现操作,它就不会成功运行。

至于为什么它们都不必是动态的,编译器基本上会尝试在与签名匹配的操作中涉及的任何一个类型上找到一个运算符(静态方法),从 LValue 开始。由于 LValue 是动态的,编译器必须假定该操作存在于将用作 X 的任何东西上,即使 X 与 Y 具有相同的占位符类型,并且不知道 Y 具有 + 运算符。

于 2012-05-04T16:55:07.893 回答