返璞归真:C#4方法重载和动态类型

C# 3.0 introduced the implicit type "var". I've explained var as saying:

C#3.0引入了隐式类型“ var” 。 我已经向var解释说:

"I'm too lazy to tell you the type of this variable, so you figure it out, compiler."

“我懒得告诉你这个变量的类型,所以编译器就弄清楚了。”

However, it's more useful than just promoting terseness or laziness:

但是,它比仅仅促进简洁或懒惰更有用:

var i = 10; // implicitly typed
int i = 10; //explicitly typed

Although var is a great way to start arguments about coding standards at your work, there are times when it is required around anonymous types. Here's an example from MSDN:

尽管var在您的工作中引发有关编码标准争论的好方法,但有时在匿名类型中还是需要使用var。 这是MSDN示例

/ Example: var is required because
// the select clause specifies an anonymous type
var custQuery = from cust in customers
where cust.City == "Phoenix"
select new { cust.Name, cust.Phone };

// var must be used because each item
// in the sequence is an anonymous type
foreach (var item in custQuery)
{
Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
}

C# 4 (not 4.0, the marketing folks say it's .NET 4, etc.) adds the dynamic keyword. I've explained this saying:

C#4(不是4.0,市场营销人员说它是.NET 4,等等)添加了dynamic关键字。 我已经解释了这句话:

"There's no way for you or I to know the type of this now, compiler, so let's hope that the runtime figures it out."

“现在,您或我都无法知道编译器的类型,所以希望运行时解决它。”

Here's how this looks from an Intellisense point of view. Here I'm hovering over the dynamic keyword:

这是从Intellisense角度看的样子。 在这里,我将鼠标悬停在dynamic关键字上:

dynamiccalc1

And here is the tooltip after pressing "." after "calc."

这是按“”后的工具提示。 在“计算”之后。

dynamiccalc2

Now, to the interesting question of the day. Christoff Turner asked this question, essentially:

现在,到今天有趣的问题。 Christoff Turner基本上问了这个问题:

"I noticed the following while doing some research within C# 4.0:"

“在C#4.0中进行一些研究时,我注意到以下内容:”

using System;
namespace ConsoleApplication1
{
class Program
{
static void f(Int32 x) { }
static void f(dynamic x) {}
static void f(Int32 x, dynamic y) {}
static void f(dynamic x, Int32 y) {}
static void f(Int32 x, dynamic y, Int32 z) {}
static void f(dynamic x, Int32 y, dynamic z) {}
static void Main(string[] args)
{
f(10); // Works - obvious
f(10, 10); // Ambiguous - obvious
f(10, 10, 10); // Ambiguous - not so obvious - since it should be possible to resolve
}
}
}

"Looking at f(10,10,10), what is the reasoning behind this call being ambiguous?"

“看f(10,10,10),此调用背后的原因是什么?”

I stared it it a while longer, then realized what is happening, and called Mads Torgersen to confirm. Mads says this.

我盯着它看了一会儿,然后意识到发生了什么,然后打电话给Mads Torgersen确认。 疯子这样说。

In short, the behavior is totally by design:

简而言之,该行为完全是设计使然:

  • dynamic in method signatures doesn’t come into it: it behaves like System.Object does.

    方法签名中没有动态的:它的行为就像System.Object一样。

  • Given that, neither of the ternary signatures is better because each fits better than the other on some arguments (Int32 fits 10 better than object does)

    鉴于此,三元签名中的任何一个都不是更好的,因为在某些参数上,每个三元签名都比另一个更合适(Int32比对象更适合10)

The key point here, in bold, because it's significant is: having the type dynamic means “use my runtime type for binding”.

此处用黑体表示的关键点是因为它很重要,因为它具有动态类型意味着“使用我的运行时类型进行绑定”。

The problem in the context of method calls is that you can't use the runtime type of something until, um, runtime. ;) Binding with dynamic expressions (dynamic binding) happens at runtime.  In this case, we're compiling against method signatures that are known at compile type and we're compiling with a (mostly) static language, so there's no dynamic method dispatching happening that could select a different method overload at runtime.

方法调用上下文中的问题是,直到运行时,您才能使用某些东西的运行时类型。 ;)使用动态表达式进行绑定(动态绑定)在运行时进行。 在这种情况下,我们将针对编译类型已知的方法签名进行编译,并使用(主要是)静态语言进行编译,因此不会发生动态方法分派,该动态方法分派可以在运行时选择不同的方法重载。

The dynamic type is statically-typed as dynamic. The compile-time type is "dynamic" (but really it's object, hence the method overloading trouble.)

动态类型被静态类型化为动态。 编译时类型是“动态的”(但实际上它是对象,因此方法重载很麻烦。)

Another way to look at this is with Reflector. This C# code:

另一种解决方法是使用Reflector 。 此C#代码:

static void f(Int32 x, dynamic y, Int32 z) {}

is essentially this, from a method signature point of view:

从方法签名的角度来看,本质上是这样的:

static void f(int x, [Dynamic] object y, int z) {}
and if there was a method that returned dynamic, it'd look like this: 

[return: Dynamic]
private static object GetCalculator() {}

So, given how dynamic works as a type, how the DLR works in the context of method dispatching, etc, you can see why things didn't work like Christoff thought they would.

因此,考虑到动态作为类型的工作方式,DLR在方法分派的上下文中的工作方式等,您可以了解为什么事情没有像Christoff认为的那样起作用。

Enjoy!

请享用!

Related Links

相关链接

翻译自: https://www.hanselman.com/blog/back-to-basics-c-4-method-overloading-and-dynamic-types

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值