C# 为什么编译器允许将Convert.ToString()赋值给整数?

C# 为什么编译器允许将Convert.ToString()赋值给整数?,c#,.net,C#,.net,我无意中在我的代码中发现了类似于以下内容的东西,它编译得很好,但显然在运行时会爆炸: dynamic fiftySixDynamic = 56; int fiftySixInt = System.Convert.ToString(fiftySixDynamic); Convert.ToString()的每个重载都会返回一个字符串,所以肯定不应该编译它?这里发生了什么?您正在使用dynamic作为Convert.ToString的输入。因为输入是动态的,所以方法绑定和类型检查延迟到运行时,因此编

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

dynamic fiftySixDynamic = 56;
int fiftySixInt = System.Convert.ToString(fiftySixDynamic);

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

您正在使用
dynamic
作为
Convert.ToString
的输入。因为输入是
动态的
,所以方法绑定和类型检查延迟到运行时,因此编译器看不到唯一可能的返回类型是
字符串
。编译器基本上停止了所有绑定和类型检查

即使调用了
fiftySixInt=fiftySixDynamic.ToString()
,它不能有返回
int
的重载,也不会从编译器得到任何警告

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

int fiftySixInt = (string)System.Convert.ToString(fiftySixDynamic);

它看起来是多余的,但它告诉编译器为了绑定的目的将返回值作为
字符串处理。该方法仍然在运行时绑定,因此,如果返回类型不是字符串,则会出现运行时异常,但下游方法会在编译时绑定。

@JMK就是其中的威力和危险所在,对于
dynamic
@JMK,当您关闭编译器并告诉它不要执行任何类型检查时,您会惊讶于它没有通知您正在执行对给定类型无效的操作?如果你想让编译器告诉你一个操作的类型是否有效,不要关闭它。这对我来说确实很奇怪。我可以理解,编译器不会捕获使用int-fiftySixInt=fiftySixDynamic.ToString()的情况,因为无法知道动态对象上的ToString方法将返回什么数据类型。但是,当使用System.Convert.ToString时,我希望编译器能够捕获它。System.Convert.ToString将是已知的方法,它将知道返回字符串,而不管传入的类型如何。我只需要使用dynamic一次,但现在我知道这是需要注意的。@Servy我当然对此感到惊讶。我会说这是一个bug。@chrismaric如果你告诉编译器不做任何类型检查,你会惊讶于它不做任何类型检查吗?该功能的语言专门用于关闭类型检查。它的设计就是为了做到这一点。如果你想让编译器进行类型检查,那么不要显式地关闭类型检查。当你特意阻止编译器进行类型检查时,它不会进行类型检查,这不是一个bug。我的建议是将此作为bug发布。。我真的不确定哪一个地方会马上消失。@chrismaric这正是它应该做的。如果它没有编译,那将是一个bug。这突出了C#中的一个弱点——程序员不清楚哪些表达式关闭了类型检查。语言设计者在使用不安全的{}@Servy时做得更好。破碎的期望=臭虫。@chrismaric所以你是说你不知道“臭虫”这个词的意思。可以