注意这不是关于如何在 C# 中实现或模拟 duck typing 的问题...
几年来,我一直认为某些 C# 语言功能依赖于语言本身定义的数据结构(对我来说,这似乎总是奇怪的先有鸡还是先有蛋的情况)。例如,我的印象是 foreach
循环只能用于实现了 IEnumerable
的类型。
从那时起我开始明白 C# 编译器使用鸭子类型(duck typing)来确定一个对象是否可以在 foreach 循环中使用,寻找 GetEnumerator
方法而不是 IEnumerable
。这很有意义,因为它消除了先有鸡还是先有蛋的难题。
我有点困惑,为什么 using
block 和 IDisposable
似乎不是这种情况。编译器不能使用鸭子类型(duck typing)并寻找 Dispose
方法有什么特别的原因吗?这种不一致的原因是什么?
也许在 IDisposable 的幕后发生了其他事情?
讨论为什么您会曾经拥有一个带有未实现 IDisposable 的 Dispose 方法的对象超出了这个问题的范围:)
最佳答案
IDisposable
没什么特别的这里 - 但迭代器有一些特别之处。
在 C# 2 之前,在 foreach
上使用此鸭子类型(duck typing)是实现强类型迭代器的唯一方式,也是不装箱迭代值类型的唯一方式。我怀疑如果 C# 和 .NET 有泛型开始,foreach
会需要 IEnumerable<T>
相反,并没有让鸭子类型(duck typing)。
现在,编译器在我能想到的其他几个地方使用了这种鸭子类型(duck typing):
- 集合初始化器寻找合适的
Add
重载(以及必须实现IEnumerable
的类型,只是为了表明它确实是某种集合);这允许灵活地添加单个项目、键/值对等 - LINQ(
Select
等)- 这就是 LINQ 实现其灵 active 的方式,允许针对多种类型使用相同的查询表达式格式,而无需更改IEnumerable<T>
本身 - C# 5 await 表达式需要
GetAwaiter
返回具有IsCompleted
的等待者类型/OnCompleted
/GetResult
在这两种情况下,都可以更轻松地将功能添加到现有类型和接口(interface)中,而这些概念以前并不存在。
鉴于IDisposable
自第一个版本以来一直在框架中,我认为鸭子类型(duck typing) using
不会有任何好处。陈述。我知道你明确地试图打折扣有 Dispose
的原因没有实现 IDisposable
从讨论中,但我认为这是一个关键点。在语言中实现一项功能需要有充分的理由,我认为鸭子类型(duck typing)是一种超越支持已知接口(interface)的功能。如果这样做没有明显的好处,它就不会最终出现在语言中。
关于c# - 鸭子类型(duck typing)在 C# 编译器中键入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6368967/