在 C# 中实现安全的鸭子类型

发布于 2024-08-10 18:03:38 字数 694 浏览 12 评论 0原文

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

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 这正是我想要避免的。

有更好的办法吗?

编辑:显然,我所说的“安全鸭子打字”的正确术语是结构性键入

After looking at how Go handles interfaces and liking it, I started thinking about how you could achieve similar duck-typing in C# like this:

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

The DuckTyper.Adapt method would use System.Reflection.Emit to build an adapter on the fly. Maybe somebody has already written something like this. I guess it's not too different from what mocking frameworks already do.

However, this would throw exceptions at run-time if Mallard doesn't actually have the right IDuck methods. To get the error earlier at compile time, I'd have to write a MallardToDuckAdapter which is exactly what I'm trying to avoid.

Is there a better way?

edit: apparently the proper term for what I call "safe duck-typing" is structural typing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

痴梦一场 2024-08-17 18:03:38

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

鸭子类型是运行时使用的概念。编译时的类似概念是结构类型,据我所知不是由 CLR 支持。 (CLR 以主格类型为中心。)

[结构类型系统]与主格系统形成鲜明对比,主格系统的比较基于显式声明或类型名称,而鸭子类型则仅检查运行时访问的结构部分的兼容性。

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

How can you know if a cow walks like a duck and quacks like a duck if you don't have a living, breathing cow in front of you?

Duck-typing is a concept used at run-time. A similar concept at compile-time is structural typing which is AFAIK not supported by the CLR. (The CLR is centred around nominative typing.)

[A structural type system] contrasts with nominative systems, where comparisons are based on explicit declarations or the names of the types, and duck typing, in which only the part of the structure accessed at runtime is checked for compatibility.

The usual way to ensure that duck-typing throws no exception at run-time are unit-tests.

巡山小妖精 2024-08-17 18:03:38

C# 的 DuckTyping

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

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

DuckTyping for C#

Reflection.Emit is used to emit IL that directly calls the original object

I don't think this library will give you compile time errors thought, I am not sure that would be entirely feasible. Use Unit Tests to help compensate for that.

笑脸一如从前 2024-08-17 18:03:38

我认为没有其他方法会导致编译时错误。

然而,这正是单元测试的优势所在。您将编写一个单元测试来验证

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

映射是否成功。

I don't think there's another way in which you would get a compile time error.

However, this is something that Unit Testing is great for. You would write a unit test to verify that

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

successfully maps.

故事和酒 2024-08-17 18:03:38

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

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

I know that implicit interfaces (which is what Go interfaces are) were planned for VB 10 (no idea about C#). Unfortunately, they were scrapped before release (I think they didn’t even make it into beta …). It would be nice to see whether they will make an appearance in a future version of .NET.

Of course, the new dynamic types can be used to achieve much the same but this is still not the same – implicit interfaces still allow strong typing, which I find important.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文