在 C# 编译器中输入鸭子 [英] Duck typing in the C# compiler

查看:24
本文介绍了在 C# 编译器中输入鸭子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意不是关于如何在 C# 中实现或模拟鸭子类型的问题...

Note This is not a question about how to implement or emulate duck typing in C#...

多年来,我的印象是某些 C# 语言特性依赖于语言本身定义的数据结构(在我看来,这总是一种奇怪的鸡与蛋的场景).例如,我的印象是 foreach 循环只能用于实现 IEnumerable 的类型.

For several years I was under the impression that certain C# language features were depdendent on data structures defined in the language itself (which always seemed like an odd chicken & egg scenario to me). For example, I was under the impression that the foreach loop was only available to use with types that implemented IEnumerable.

从那以后我开始明白 C# 编译器使用鸭子类型来确定一个对象是否可以在 foreach 循环中使用,寻找 GetEnumerator 方法而不是 IEnumerable.这很有意义,因为它可以去除鸡肉和鸡蛋难题.

Since then I've come to understand that the C# compiler uses duck typing to determine whether an object can be used in a foreach loop, looking for a GetEnumerator method rather than IEnumerable. This makes a lot of sense as it removes the chicken & egg conundrum.

我有点困惑,为什么 using 块和 IDisposable 似乎不是这种情况.编译器是否有任何特殊原因不能使用鸭子类型 &寻找 Dispose 方法?这种不一致的原因是什么?

I'm a little confused as to why this isn't doesn't seem to be the case with the using block and IDisposable. Is there any particular reason the compiler can't use duck typing & look for a Dispose method? What's the reason for this inconsistency?

也许 IDisposable 的幕后还有其他事情发生?

Perhaps there's something else going on under the hood with IDisposable?

讨论为什么您会永远拥有一个带有未实现 IDisposable 的 Dispose 方法的对象,这超出了这个问题的范围:)

Discussing why you would ever have an object with a Dispose method that didn't implement IDisposable is outside the scope of this question :)

推荐答案

这里的 IDisposable 没有什么特别之处 - 但迭代器有一些特别之处.

There's nothing special about IDisposable here - but there is something special about iterators.

在 C# 2 之前,在 foreach 上使用这种鸭子类型是 only 是您可以实现强类型迭代器的唯一方法,也是迭代值类型的唯一方法没有拳击.我怀疑如果 C# 和 .NET 有泛型开始,foreach 将有 required IEnumerable<T> 相反,没有鸭子打字.

Before C# 2, using this duck type on foreach was the only was you could implement a strongly-typed iterator, and also the only way of iterating over value types without boxing. I suspect that if C# and .NET had had generics to start with, foreach would have required IEnumerable<T> instead, and not had the duck typing.

现在编译器在我能想到的其他几个地方使用了这种鸭子类型:

Now the compiler uses this sort of duck typing in a couple of other places I can think of:

  • 集合初始化器寻找合适的 Add 重载(以及必须实现 IEnumerable 的类型,只是为了表明它确实是某种集合);这允许灵活添加单个项目、键/值对等
  • LINQ (Select 等) - 这就是 LINQ 实现其灵活性的方式,允许针对多种类型使用相同的查询表达式格式,而无需更改 IEnumerable<T> 本身
  • C# 5 await 表达式要求 GetAwaiter 返回具有 IsCompleted/OnCompleted/GetResult 的 awaiter 类型
  • Collection initializers look for a suitable Add overload (as well as the type having to implement IEnumerable, just to show that it really is a collection of some kind); this allows for flexible adding of single items, key/value pairs etc
  • LINQ (Select etc) - this is how LINQ achieves its flexibility, allowing the same query expression format against multiple types, without having to change IEnumerable<T> itself
  • The C# 5 await expressions require GetAwaiter to return an awaiter type which has IsCompleted / OnCompleted / GetResult

在这两种情况下,都可以更轻松地将功能添加到现有类型和接口中,而这个概念之前并不存在.

In both cases this makes it easier to add the feature to existing types and interfaces, where the concept didn't exist earlier on.

鉴于 IDisposable 自第一个版本以来一直在框架中,我认为鸭子键入 using 语句没有任何好处.我知道您在讨论中明确试图打折使用 Dispose 而不实现 IDisposable 的原因,但我认为这是一个关键点.在语言中实现一个特性需要有充分的理由,我认为鸭子类型是一个超越支持已知接口的特性.如果这样做没有明显的好处,它就不会出现在语言中.

Given that IDisposable has been in the framework since the very first version, I don't think there would be any benefit in duck typing the using statement. I know you explicitly tried to discount the reasons for having Dispose without implementing IDisposable from the discussion, but I think it's a crucial point. There need to be good reasons to implement a feature in the language, and I would argue that duck typing is a feature above-and-beyond supporting a known interface. If there's no clear benefit in doing so, it won't end up in the language.

这篇关于在 C# 编译器中输入鸭子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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