为什么一个方法调用前pression有型动态即使是只有一个可能的返回类型? [英] Why does a method invocation expression have type dynamic even when there is only one possible return type?

查看:167
本文介绍了为什么一个方法调用前pression有型动态即使是只有一个可能的返回类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题启发。

短版:为什么不能编译器弄清楚的编译时类型 M(动态ARG)如果只有一个过载 M 或全部 M 具有相同的返回类型的?

Short version: Why can't the compiler figure out the compile-time type of M(dynamic arg) if there is only one overload of M or all of the overloads of M have the same return type?

每规范,第7.6.5节:

Per the spec, §7.6.5:

这是调用-EX pression动态绑定(§7.2.2)如果以下至少一人持有:

An invocation-expression is dynamically bound (§7.2.2) if at least one of the following holds:


      
  • 主要-EX pression具有编译时类型动态。

  • The primary-expression has compile-time type dynamic.

至少有一个参数的编译时类型动态和主-EX pression没有委托类型。

At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.

这是有道理的,对于

class Foo {
    public int M(string s) { return 0; }
    public string M(int s) { return String.Empty; }
}

编译器无法弄清楚的编译时类型

the compiler can't figure out the compile-time type of

dynamic d = // dynamic
var x = new Foo().M(d);

,因为它不会知道,直到运行时其超载的 M 被调用。

但是,为什么不能编译搞清楚编译时的类型,如果 M 只有一个过载或全部的重载并购返回相同类型?

However, why can't the compiler figure out the compile-time type if M has only one overload or all of the overloads of M return the same type?

我期待明白为什么规范没有让编译器在编译时静态键入这些前pressions。

I'm looking to understand why the spec doesn't allow the compiler to type these expressions statically at compile time.

推荐答案

更​​新:这个问题问得的我在十月,2012 22日博客的主题。感谢伟大的问题!

UPDATE: This question was the subject of my blog on the 22nd of October, 2012. Thanks for the great question!

为什么不能编译器弄清楚的编译型型 M(dynamic_ex pression)如果M的只有一个过载或全部M的重载具有相同的返回类型?

Why can't the compiler figure out the compile-type type of M(dynamic_expression) if there is only one overload of M or all of the overloads of M have the same return type?

编译器的可以的搞清楚编译时类型;编译时类型的动态的,并且编译器的数字表示出来成功。

The compiler can figure out the compile-time type; the compile-time type is dynamic, and the compiler figures that out successfully.

我觉得你打算问的问题是:

I think the question you intended to ask is:

为什么的编译时类型 M(dynamic_ex pression)总是动态的,甚至在你正在做一个完全不必要罕见的,不太可能的情况下一种方法M动态调用将始终无论选择何种参数类型的?

Why is the compile-time type of M(dynamic_expression) always dynamic, even in the rare and unlikely case that you're making a completely unnecessary dynamic call to a method M that will always be chosen regardless of the argument type?

在短语这样的问题,它有点回答自己。 : - )

When you phrase the question like that, it kinda answers itself. :-)

原因之一:

你设想是罕见的案件;为了使编译器能够让你描述的那种推理,必须知道足够的信息,以便编译器可以做前pression几乎全静态类型的分析。但是,如果你是在这种情况那么你为什么要摆在首位使用动态?你会做的更好,以简单地说:

The cases you envision are rare; in order for the compiler to be able to make the kind of inference you describe, enough information must be known so that the compiler can do almost a full static type analysis of the expression. But if you are in that scenario then why are you using dynamic in the first place? You would do far better to simply say:

object d = whatever;
Foo foo = new Foo();
int x = (d is string) ? foo.M((string)d) : foo((int)d);

显然,如果只存在一个M的过载则它更容易:投射到物体向期望的类型的。如果无法在运行时,因为投它坏的,好,动态就失败了呢!

Obviously if there is only one overload of M then it is even easier: cast the object to the desired type. If it fails at runtime because the cast it bad, well, dynamic would have failed too!

有根本没有的需求的动态在这些各种各样的场景放在首位,所以我们为什么会在编译器做了很多昂贵和困难类型推断工作,使一个场景中,我们不要不想你首先使用动态?

There's simply no need for dynamic in the first place in these sorts of scenarios, so why would we do a lot of expensive and difficult type inference work in the compiler to enable a scenario we don't want you using dynamic for in the first place?

理由二:

假设我们确实说过重载具有非常特殊的规则,如果该方法组是静态已知含有的一种方法。大。现在我们只是增加了一个新的脆弱性的语言。现在的添加一个新的过载调用的返回类型更改为一个完全不同类型的的 - 这样一种类型,不仅会导致动态语义,还箱值类型。别急,还有更糟糕!

Suppose we did say that overload resolution has very special rules if the method group is statically known to contain one method. Great. Now we've just added a new kind of fragility to the language. Now adding a new overload changes the return type of a call to a completely different type -- a type which not only causes dynamic semantics, but also boxes value types. But wait, it gets worse!

// Foo corporation:
class B
{
}

// Bar corporation:
class D : B
{
    public int M(int x) { return x; }
}

// Baz corporation:
dynamic dyn = whatever;
D d = new D();
var q = d.M(dyn);

让我们假设我们实现您的功能requiest和推断,q是INT,你的逻辑。现在美孚公司补充说:

Let's suppose that we implement your feature requiest and infer that q is int, by your logic. Now Foo corporation adds:

class B
{
    public string M(string x) { return x; }
}

和突然当巴兹公司重新编译他们的code,Q突然类型悄然变成动态的,因为我们不知道在编译时即达因不是字符串。这是一个的离奇的和意想不到的静态分析的变化!为什么要第三方添加新的方法的基类的引起局部变量的类型在一个完全不同的方法来改变是在不同的公司编写了一个完全不同的类,一个公司,甚至不直接使用B,但只通过D?

And suddenly when Baz corporation recompiles their code, suddenly the type of q quietly turns to dynamic, because we don't know at compile time that dyn is not a string. That is a bizarre and unexpected change in the static analysis! Why should a third party adding a new method to a base class cause the type of a local variable to change in an entirely different method in an entirely different class that is written at a different company, a company that does not even use B directly, but only via D?

这是脆基类问题的一种新形式,我们寻求在C#中尽量减少脆基类的问题。

This is a new form of the Brittle Base Class problem, and we seek to minimize Brittle Base Class problems in C#.

或者,如果不是富CORP说:

Or, what if instead Foo corp said:

class B
{
    protected string M(string x) { return x; }
}

现在,你的逻辑,

var q = d.M(dyn);

给Q上的int类型时,上面的code是的之外的由D继承的类型的,但

var q = this.M(dyn);

给出q的​​类型为动态时的的是由D继承的类型!作为一个开发者,我会发现相当惊人。

gives the type of q as dynamic when inside a type that inherits from D! As a developer I would find that quite surprising.

原因三:

有在C#中已经太多聪明。我们的目标不是建立一个逻辑引擎,可以制定出给定一个特定的程序的所有可能值的所有可能的类型限制。我们preFER有一般的,可以理解的,COM prehensible可以很容易地记录下来,并没有错误实施的规则。该规范已经是八百页长,写没有bug的编译器是非常困难的。我们不要变得更加困难。且不说牺牲的测试的所有那些疯狂的情况下。

There is too much cleverness in C# already. Our aim is not to build a logic engine that can work out all possible type restrictions on all possible values given a particular program. We prefer to have general, understandable, comprehensible rules that can be written down easily and implemented without bugs. The spec is already eight hundred pages long and writing a bug-free compiler is incredibly difficult. Let's not make it more difficult. Not to mention the expense of testing all those crazy cases.

理由四:

此外:语言能提供你许多机会,利用静态类型分析仪自己。如果您使用的是动态的,你的专门要求该分析仪推迟动作,直到运行时。它不应该是使用停在编译时做静态类型分析功能使静态类型分析,在编译时不能很好地工作一个惊喜。

Moreover: the language affords you many opportunities to avail yourself of the static type analyzer. If you are using dynamic, you are specifically asking for that analyzer to defer its action until runtime. It should not be a surprise that using the "stop doing static type analysis at compile time" feature causes static type analysis to not work very well at compile time.

这篇关于为什么一个方法调用前pression有型动态即使是只有一个可能的返回类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆