简体   繁体   English

设计一个可以从F#中使用的C#库的指南

[英]Guidelines to design a C# library well usable from F#

I just want to point out that this is question is not the reverse of 我只是想指出,这个问题不是相反的

Best approach for designing F# libraries for use from both F# and C# 设计F#库以供F#和C#使用的最佳方法

Here I'm not asking how to design a functional library written C# to be used in both worlds. 在这里,我不是要问如何设计一个用于两个世界的C#函数库。

I'd like to know good practices on what design choices embrace or avoid to get a reasonable compromise for make this library usable from F# . 我想知道什么样的设计选择包含或避免获得合理的折衷方案以使这个库可以从F#中使用的 良好实践

Practices like (for example): 像(例如)的做法:

  • keep object hierarchy as simple as possible 保持对象层次结构尽可能简单

  • avoid mutating state of objects, but return new ones 避免改变对象的状态,但返回新的对象

  • etc... 等等...

Anyone that already done it, can share it's experience? 任何已经完成它的人都可以分享它的经验吗?

Side note 边注

It's interesting note this OSS project, IronJS . 有趣的是,这个OSS项目IronJS Yes, it's written in F#, but the author expose two specialized host IronJS.Hosting.FSharp and IronJS.Hosting.CSharp . 是的,它是用F#编写的,但是作者公开了两个专门的主机IronJS.Hosting.FSharpIronJS.Hosting.CSharp

Interop with existing .NET libraries was a major design goal of F#, so there aren't any constraints on the libraries to be consumed. 与现有.NET库互操作是F#的主要设计目标,因此对要使用的库没有任何限制。

That said, because of F#'s stricter typing, there are some patterns that result in slightly clunkier code. 也就是说,由于F#更严格的打字,有些模式导致代码略显笨拙。 The builder pattern is one. 构建器模式是一个。

var bldr = new StringBuilder();
bldr.Append("abc"); //ignoring return value

vs.

bldr.Append("abc") |> ignore //must be explicitly ignored

But this is easily worked around using an extension method or let-bound function. 但这很容易使用扩展方法或let-bound函数。 Bottom line: interop is one of F#'s strengths and greatest achievements. 底线:互操作是F#的优势和最大成就之一。

Imagine one day you would like to rewrite your C# library in F# for better usability. 想象一下,有一天你想用F#重写你的C#库以获得更好的可用性。 Here are the paths you are likely to take: 以下是您可能采取的路径:

在此输入图像描述

I focus on the path "Imperative C# --> Functional C# --> Functional F# --> Idiomatic F#". 我专注于“命令C# - >功能C# - >功能F# - >惯用F#”的路径。 The more functional your C# library is, the more usable your library is in F# . 您的C#库功能越多,您的库在F#中的可用性就越大 Functional style helps increase composability and is closer to idiomatic F# code. 功能风格有助于提高可组合性,并且更接近于惯用的F#代码。 Along these lines, you can: 沿着这些方向,你可以:

  • Embrace immutability by default principle. 默认拥抱不变性原则。 If you don't know whether you need to update a field/property later, just mark it readonly first. 如果您不知道以后是否需要更新字段/属性,请先将其标记为readonly
  • Follow expression-based and declarative programming style. 遵循基于表达式和声明性编程风格。 LINQ operations are good examples. LINQ操作就是很好的例子。
  • Use immutable collections or mutable collections in an immutable way. 以不可变的方式使用不可变集合或可变集合。 With the introduction of C# immutable collections , it should be easier than ever before. 随着C#immutable集合引入 ,它应该比以往更容易。

The picture above is taken from F# for fun and profit 's Porting from C# to F# series . 上图是从F#中获取的乐趣和利润 从C#移植到F#系列 They are very helpful; 他们非常有帮助; knowing how C# concepts are expressed in F# will improve usability of your library. 了解如何在F#中表达C#概念将提高库的可用性。

It's hard to avoid C#'s object-oriented features. 很难避免C#的面向对象特性。 Remember that F# type inference doesn't work very well with these features. 请记住,F#类型推断对这些功能不起作用。 Along the line of keeping object hierarchy simple, you should reduce number of member overloads. 沿着保持对象层次结构简单的方法,您应该减少成员重载的数量。 A big number of member overloads will easily confuse F# type checker. 大量的成员重载很容易混淆F#类型检查器。 Moreover, it doesn't hurt to distribute a thin F# wrapper with your C# library . 而且, 使用C#库分发一个瘦F#包装器并没有什么坏处。 Certain things you need to do are turning some methods into module functions and creating Active Patterns to decompose object hierarchy. 您需要做的一些事情是将一些方法转换为模块函数并创建活动模式以分解对象层次结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM