为什么编译器允许将Convert.ToString()分配给整数?

JMK*_*JMK 14 .net c#

我偶然在我的代码中偶然发现了类似于以下内容的东西,它编译得很好但是在运行时显然是炸弹:

dynamic fiftySixDynamic = 56;
int fiftySixInt = System.Convert.ToString(fiftySixDynamic);
Run Code Online (Sandbox Code Playgroud)

Convert.ToString()的每个重载都返回一个字符串,所以这肯定不会编译?这里发生了什么?

D S*_*ley 36

你正在使用dynamic输入Convert.ToString.因为输入是dynamic,方法绑定和类型检查被推迟到运行时,所以编译器没有看到唯一可能的返回类型string.编译器基本上停止了该点的所有绑定和类型检查.

即使你叫fiftySixInt = fiftySixDynamic.ToString(),它不能有一个返回值的过载int,你不会得到来自编译器的任何警告.

避免编译时错误仍然允许动态行为的一种方法是转换返回:

int fiftySixInt = (string)System.Convert.ToString(fiftySixDynamic);
Run Code Online (Sandbox Code Playgroud)

它看起来多余,但它告诉编译器将返回值视为string用于绑定目的.该方法仍然在运行时绑定,因此如果返回类型不是字符串,您将获得运行时异常,但下游方法将在编译时绑定.

  • @JMK当你关闭编译器并告诉它不要进行任何类型检查它没有通知你你正在执行对给定类型无效的操作时,你会感到惊讶吗?如果希望编译器告诉您操作类型是否有效,请不要将其关闭. (6认同)
  • 这对我来说似乎很奇怪.我可以理解使用int fiveSixInt = fiftySixDynamic.ToString()不会被编译器捕获,因为无法知道动态上的ToString方法将返回什么数据类型.但是,当使用System.Convert.ToString时,我希望编译器能够捕获它.System.Convert.ToString将是已知的方法,它知道有一个字符串的返回,无论传入的类型.我只需要使用动态一次,但现在我知道这是需要注意的事情. (4认同)
  • @JMK其中存在着"动态"的力量和危险. (3认同)
  • @ChrisMarisic如果您告诉编译器不进行任何类型检查它不进行任何类型检查,您会感到惊讶吗?该功能在语言中专门用于关闭类型检查.它的字面设计就是为了做到这一点.如果您希望编译器进行类型检查,那么不要显式关闭类型检查当您不采取行动阻止编译器进行类型检查时它不会进行类型检查,这不是一个错误. (2认同)