17

在看了Go如何处理接口并喜欢它之后,我开始思考如何在 C# 中实现类似的鸭子类型,如下所示:

var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);

DuckTyper.Adapt方法将用于System.Reflection.Emit动态构建适配器。也许有人已经写过这样的东西。我想这与模拟框架已经做的并没有太大的不同。

Mallard但是,如果实际上没有正确的IDuck方法,这将在运行时引发异常。为了在编译时更早地得到错误,我必须写一个MallardToDuckAdapter这正是我想要避免的。

有没有更好的办法?

编辑:显然,我称之为“安全鸭式打字”的恰当术语是结构打字

4

4 回答 4

14

如果你面前没有一头活生生的、会呼吸的牛,你怎么知道一头牛是否像鸭子一样走路和嘎嘎叫?

Duck-typing 是在运行时使用的概念。编译时的一个类似概念是结构类型,这是 CLR 不支持的 AFAIK。(CLR 以主格类型为中心。)

[结构类型系统] 与主格系统(其中比较基于显式声明或类型名称)和鸭式类型(其中仅检查在运行时访问的结构部分的兼容性)形成对比。

确保鸭子类型在运行时不抛出异常的常用方法是单元测试。

于 2009-11-13T17:28:11.033 回答
5

C# 的 DuckTyping

Reflection.Emit 用于发出直接调用原始对象的 IL

我不认为这个库会给你编译时错误的想法,我不确定这是否完全可行。使用单元测试来帮助弥补这一点。

于 2009-11-13T17:25:04.377 回答
1

我认为没有另一种方式会导致编译时错误。

但是,这是单元测试非常适合的事情。您将编写一个单元测试来验证

DuckTyper.Adapt<Mallard, IDuck>(mallard);

成功映射。

于 2009-11-13T17:30:26.347 回答
1

我知道隐式接口(Go 接口是什么)是为 VB 10 计划的(不知道 C#)。不幸的是,它们在发布之前就被废弃了(我认为它们甚至没有进入测试版……)。很高兴看到它们是否会出现在 .NET 的未来版本中。

当然,新dynamic类型可以用来实现很多相同的功能,但这仍然不一样——隐式接口仍然允许强类型,我认为这很重要。

于 2009-11-13T17:34:39.477 回答