【问题标题】:Operator with C# dynamic?具有 C# 动态的运算符?
【发布时间】:2012-05-04 16:44:55
【问题描述】:

我有这个功能:

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 可以是 + 到其他东西)?

【问题讨论】:

  • 执行代码后result中的值是多少?是“3”还是“12”。我的猜测是它在进行字符串连接。
  • @Servy:是什么让你认为当Tint 时它会进行字符串连接?

标签: c# dynamic .net-4.0 clr


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 另外,我想知道为什么你会让一个泛型方法尝试使用类型特定的运算符而没有约束。
  • 好吧,对于像数字类型这样的东西,您无法提出任何允许算术运算的类型约束。
  • 我认为首选的方法是像框架一样为那些特定的值类型进行重载。否则,如果您想让特定类型执行某种操作,请让它们实现特定接口,然后约束到该接口。
  • 一个人为的例子是尝试实现Complex&lt;T&gt;。接口、重载和泛型都不允许您仅使用语法来实现算术运算。
  • 所以1个参数是动态的就足够了,所以整个表达式将被评估为动态的?
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2019-07-22
    • 2021-10-06
    • 2010-11-15
    • 2016-01-05
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    相关资源
    最近更新 更多