C# 编译器为什么处理Func<;的返回类型;动态,int>;强类型?

C# 编译器为什么处理Func<;的返回类型;动态,int>;强类型?,c#,dynamic,func,C#,Dynamic,Func,为什么要编译下面的代码?编译器似乎有足够的信息知道尝试的赋值无效,因为Func的返回类型不是动态的 Func<dynamic, int> parseLength = whatever => whatever.Length; dynamic dynamicString = "String with a length"; DateTime wrongType = parseLength(dynamicString); Func parseLength=whatever=>what

为什么要编译下面的代码?编译器似乎有足够的信息知道尝试的赋值无效,因为Func的返回类型不是动态的

Func<dynamic, int> parseLength = whatever => whatever.Length;
dynamic dynamicString = "String with a length";
DateTime wrongType = parseLength(dynamicString);
Func parseLength=whatever=>whatever.Length;
DynamicDynamicString=“具有长度的字符串”;
DateTime错误类型=parseLength(dynamicString);

由于输入是动态的,编译器甚至无法确定函数的结果是否为int。它将在函数执行时尝试将结果转换为int,如果无法执行,则会失败。现在,如果您问为什么在静态类型约束无法强制执行的情况下,您甚至可以构造这样的代码,请记住,动态与其说是一种类型,不如说是一个警告标志,“您的常规静态类型规则在这里不适用”

查看“动态传染”的概念,了解更多信息。

如果类型的任何部分是动态的,编译器必须将整个内容视为动态的。因此:

Func<dynamic, int> parseLength = <some func>  // is dynamic and type cannot be evaluated until runtime.
这将编译,并且正如您所期望的,将产生运行时错误

在某些情况下,动态键入很有用。我个人的经验是访问COM组件中的非托管代码

它基本上是告诉编译器,“相信我,这会起作用的.=)”或“这些不是你要找的机器人”

编译器似乎有足够的信息知道尝试的赋值是无效的,因为
Func
的返回类型不是动态的

Func<dynamic, int> parseLength = whatever => whatever.Length;
dynamic dynamicString = "String with a length";
DateTime wrongType = parseLength(dynamicString);
警告:当然,我不再代表C#设计团队发言;这是我对语言设计的看法

所以你在这里说的是“我禁用了一个安全系统。为什么禁用的安全系统没有检测到我做了什么危险的事情并阻止我?”好吧,如果这是你想要的,那么也许你不应该首先禁用安全系统

也就是说,你是对的;“禁用”型安全系统实际上可以在这里继续工作,并检测到您正在做危险的事情。事实上,在许多情况下,足够聪明的编译器可以对动态子表达式进行类型推断。你找到了其中一个。实现必要的分析是一个特性请求

因此,现在相关的问题是:为了给开发团队设计、规范、实现、测试、调试、发布和永久维护一个静态地发现程序中的bug的特性(开发人员明确要求关闭静态检查),您希望削减C#的哪个特性?请记住,成本包括确保语言的未来特性不会干扰编译器进行此推断的能力;其中一些成本是由设计团队在未来支付的税费


在少数情况下,静态分析包含
动态
的表达式;例如,有一些重载解析问题涉及带有动态参数的静态方法,编译器可以并且确实发现,无论在运行时提供什么,重载解析都将失败。但除了这几个案例之外,语言设计团队一直认为,巴克把有限的预算花在你已经确定的场景上是不好的

我想当涉及到
动态
时,编译器可能会有点盲目,但您最好等待更有知识的人,也许是缩写为J.S的人。有没有方法调用Eric Lippert?
动态
在运行时得到评估,因此,在
Func
中存在
dynamic
参数似乎会导致在运行时对
Func
进行评估(即使静态分析可以发现它将输出
int
)@JonB-Eric Lippert确实写了几篇关于这个主题的文章(谷歌“动态传染”)。可能与@JonB重复:如果你想引起我的注意,你可以在我的博客或推特上用
@ericlippert
留言。请注意,没有明示或暗示任何服务级别协议。但是编译器并不完全将整个Func视为动态的,因为这会产生编译时错误:Func parseLength=where=>“string而不是int”;啊,真有趣。我同意@EricLippert的答案。一定有什么东西仍然在对代码执行一些静态分析,可能是因为它在已知类型的Func中是动态的。@mattbob:您是否希望
int M(dynamic d){return”“;}
推理“因为形式参数
d
是动态的,返回的值不需要与返回类型匹配”对不起,如果你没问我。在我看来,无论形式参数如何,这个示例都可能是编译器静态理解为错误的。如果返回值是“returnsomestringfunc(d);”,编译器甚至可能知道有问题。但实施成本的论点是有道理的。我理解你的“成本”论点的重要性,它回答了我的问题。接下来,如果将此功能添加到语言中是免费的,那么有什么理由不这样做吗?@mattbob:没有“免费”功能,因此我们现在从错误的前提进行推理,因此是不可靠的。这就是说:即使成本很低,该功能是否有足够的固有缺陷使其价值较低?我一点也没想到,好奇心也没什么不好的。您现在已经满意了,谢谢。