具有 C# 动态的运算符

本文关键字:运算符 动态 具有 | 更新日期: 2023-09-27 18:33:17

我有这个功能:

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 行是正常的,而第 2 行是 BANG (在编译时(。

第 2 行引发的异常是:

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

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

但是1号线呢?它不应该也需要动态演员y吗?

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

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

具有 C# 动态的运算符

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

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

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

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

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

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

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