如何在接口上添加 SRTP 约束?

How do I add SRTP constraints on an interface?

假设我想要一个带有成员 Write 的接口,该接口接受约束为具有 Id: int 字段的泛型类型。

这在 F# 中可行吗?我试过这个和它的变体,但总是得到 The code is not sufficiently generic. The type variable... would escape its scope. 错误。

其他类似问题建议使用内联成员,但这在接口上是不可能的。

type IDatabase<'T when 'T : (member Id: int)> =
    abstract member Save: 'T -> unit

是否有任何原因导致您不能使用 .NET 运行时支持的普通接口约束?

type IEntity = 
  abstract Id : int

type IDatabase<'T when 'T :> IEntity> =
  abstract member Save: 'T -> unit

使用 SRTP 和接口之间有两个主要区别:

  • .NET 运行时直接支持接口约束,F# 利用它,因此约束编译为 .NET 约束。使用 SRTP,必须在编译时满足约束,这会施加各种限制。

  • 如果你引入一个接口,你必须能够修改所有你希望能够处理(实现接口)的类。使用 SRTP,您可以依靠“鸭子打字”和一个恰好已经存在的成员 类 您关心的。

如果第二个条件对你来说不是太严格(即你控制所有 类),那么接口是一个更简单的选择。