【问题标题】:C# compiler type inference with dynamic function parameters使用动态函数参数的 C# 编译器类型推断
【发布时间】:2017-02-24 17:53:27
【问题描述】:

当我调用函数并将其中一个参数替换为动态时,编译器会推断函数结果是动态的。我不明白为什么会这样。

示例:a 的推断类型是动态的,因此此代码可以编译,但在运行时当然会失败并出现 RuntimeBinderException:

dynamic b = "";
var a = MethodWithoutOverloads("", b);
a.DoesNotExist();

...

public string MethodWithoutOverloads(string a, string b) { ... }

有人知道为什么推断的类型不是函数的返回类型吗?

编辑:编辑以明确这种情况发生在没有重载的方法上

【问题讨论】:

    标签: c# var type-inference


    【解决方案1】:

    您是对的,编译器可以推断出所有String.Format 重载都返回string,因此推断a 必须是字符串,无论b真的。

    事实上,编译器并没有这样做。它解决了一般情况,这很好,并且因为具有不同返回类型的重载在 C# 中是有效的,所以它只是将返回类型分配为动态并让运行时解决。

    回答您的具体问题,

    public string MethodWithoutOverloads(string a, string b) { ... }
    dynamic a = "";
    var result = MethodWithoutOverloads(a, a); // result is dynamic.
    

    让我们想象一下编译器决定 resultstring 并且你将你的库发布到狂野的西部。然后,稍后,您决定添加具有以下签名的重载:

    public int MethodWithoutOverloads(int a, int b) { ... } 
    

    现在,result 的类型应该是什么?而且,依赖于result 被强类型化为string 的现有代码会发生什么?

    string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable);
    

    语义完全改变;在消费者拥有一个安全的强类型变量之前,现在他突然有了一个可能不安全的隐式强制转换,可能会在运行时崩溃。

    【讨论】:

      【解决方案2】:

      因为编译器不知道在运行时会调用哪个方法。

      例如,你可能有两种方法:

      int MyMethod(int a)
      {
          return 5;
      }
      
      double MyMethod(string a)
      {
          return 6.0;
      }
      

      然后你编写以下代码:

      dynamic myThing = 5;
      var myResult = MyMethod(myThing);
      

      考虑到我们已经明确表示myThing动态,并且它的类型将在运行时确定,我们不知道将调用哪个方法(如果有)。因此,我们也不知道返回类型。

      【讨论】:

      • 当我有一种方法时,即没有歧义时,就会发生这种情况。 String.Format 不是一个很好的例子,但是当我在没有歧义的情况下调用自己的方法时,类型推断也会失败。
      • @Lev 没错。 技术上编译器可能能够毫不含糊地弄清楚它,但我认为这需要更多的工作才能获得看似不多的收益。每当dynamic 是表达式的一部分时,结果也将是dynamic。如果你确定你知道类型,只需明确变量类型而不是使用var
      • 好吧,基本上这是一个“我们没有为此案例实现类型推断”的案例......
      • @Lev 如果编译器按照你说的做,那么如果以后某天添加了一个返回其他东西的重载会发生什么?您会突然破坏现有代码,这似乎是一条脆弱的道路。
      猜你喜欢
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 2018-03-03
      • 2020-01-21
      • 1970-01-01
      相关资源
      最近更新 更多