我有几种实现接口的类型。这些类型的平等仅取决于接口成员。是否可以为这些类型定义一次,而不是为每种类型覆盖Equals
或op_Equality
?
修改
我尝试了以下操作,但无论出于何种原因,它都会覆盖=
的每次使用,即使对于未实现IEntity
的类型也是如此。
[<AutoOpen>]
module Equality =
let inline op_Equality (left:IEntity) (right:IEntity) = true
我也尝试使用灵活类型(#IEntity
)。结果相同。
答案 0 :(得分:2)
您尝试做的是mixins或类型类可能在其他语言中启用的内容;遗憾的是,F#中没有相同的功能。您最好的选择可能是以下选项之一:
在您的类型之外编写您的相等方法,然后让所有实现都遵循它。例如,
let entityEquals (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
i1.Member2 = i2.Member2 &&
...
type MyEntity() =
interface IEntity with
member x.Member1 = ...
...
override x.Equals(y) =
match y with
| :? IEntity as y -> entityEquals x y
| _ -> false
override x.GetHashCode() =
...
除了一些样板文件之外,这里的缺点是如果其他人实现了你的IEntity
接口,他们就不会被迫使用你的相等方法 - 它是选择加入的。
创建另一个用于IEntity
s:
let (==) (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
...
这个(巨大的)缺点是包含IEntity
的类型(如元组,记录等)的结构相等不会使用此运算符来比较这些组件,这很可能导致令人惊讶的破碎代码。
答案 1 :(得分:1)
我认为没有办法以静态的方式做到这一点。问题是扩展成员(例如,如果您添加op_Equality
作为扩展名)被静态成员约束忽略(例如,如果您还重新定义了{{1}使用=
并inlin
要求)。
F#编译器只有在编译FSharp.Core.dll时才有一些特殊功能可以提供帮助(搜索声明op_Equality
的来源)。它使用类似静态类型切换的东西 - 但是凡人都无法访问它。
所以,我没有比使用动态类型测试更好的想法,这不是一个好方法,而且定义一个自定义运算符来比较你的接口可能更好。
作为参考,丑陋的动态方法是:
let inline GenericOne