【问题标题】:Type checks for null-coalescing operator with dynamic operand使用动态操作数检查空合并运算符的类型
【发布时间】:2018-08-29 07:47:36
【问题描述】:

考虑以下最小示例:

class Program {
    static void Main(string[] args) {
        Dictionary<string, int> obj = GetDynamic() ?? new List<string>();
    }

    private static dynamic GetDynamic() {
        return null;
    }
}

代码将编译,但在运行时失败,因为 List&lt;T&gt; 无法转换为 Dictionary&lt;TKey, TValue&gt;。我猜这是因为表达式GetDynamic() ?? new List&lt;string&gt;() 在编译时解析为dynamic

当空合并运算符的任一操作数与预期的返回类型不匹配时,有没有办法强制编译错误?

【问题讨论】:

  • 您不能强制默认编译器在此处引发错误消息。但我想您可以开发自己的 Roslyn 扩展来生成自定义错误消息。以前没有做过类似的事情,所以我只能建议谷歌搜索“c# roslyn extension”或类似的东西。
  • 这已经发生了。真正的问题是dynamic 总是可以转换为其他东西,尽管隐式转换可能在运行时失败。这里没有(编译时)输入错误。当然,您可以强制使用:(Dictionary&lt;string, int&gt;) GetDynamic() ?? new List&lt;string&gt;()——但这需要您知道dynamic 参与其中。我能想到的所有其他解决方法都涉及更多,并且需要人为地重写 ??,除非您已经知道该问题(这违背了目的),否则您不会在实际代码中使用它们。
  • 如果你已经知道返回的类型,为什么还要使用dynamic?将dynamic 更改为Dictionary&lt;string, int&gt;,您将获得所需的编译时错误。如果您不知道返回的类型,那么您的代码设计有缺陷,当它返回除Dictionary&lt;string, int&gt; 以外的任何内容时,您将收到运行时错误。
  • @RacilHilan 这显然是一个学术问题。 GetDynamic 可能第三方 API 方法 OP 无法更改。问题的重点是“类型安全”:如何在编译时避免这种错误。
  • 该示例是从使用dynamic 进行配置的旧版应用程序中提取的。我只是在应用程序中偶然发现了这样一个错误,并想知道为什么编译器无法判断这里有什么问题(因为这对开发人员来说非常明显)。

标签: c# .net type-safety null-coalescing-operator


【解决方案1】:

为什么编译器无法判断这里有什么问题(因为这对开发人员来说非常明显)。

因为编写代码的开发人员明确告诉编译器不要检查。当我们使用dynamic 时,我们实际上是在告诉编译器关闭静态类型检查。

以这种方式使用dynamic 不是一个好的设计。如果你不知道返回的类型,那么代码设计就有缺陷,当它返回Dictionary&lt;string, int&gt; 以外的任何内容时,你仍然会遇到运行时错误。将dynamic 更改为Dictionary&lt;string, int&gt;,您将获得所需的编译时错误。

这可能会回答您的问题,但这绝不是一件好事。如果你投dynamic,你会得到编译器错误:

Dictionary<string, int> obj = (Dictionary<string, int>)GetDynamic() ?? new Dictionary<string, int>();

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2011-07-07
    • 2021-08-31
    • 2017-07-14
    • 1970-01-01
    • 2023-03-23
    • 2021-09-25
    • 2012-04-27
    • 2017-11-24
    相关资源
    最近更新 更多