我目前正在F#中实现一个Spec框架,我希望在我的should
类型中隐藏Equals,GetHashCode等方法,这样API就不会被这些混乱。
我知道在C#中,它是通过使类实现这样的接口来完成的:
using System;
using System.ComponentModel;
public interface IFluentInterface
{
[EditorBrowsable(EditorBrowsableState.Never)]
bool Equals(object other);
[EditorBrowsable(EditorBrowsableState.Never)]
string ToString();
[EditorBrowsable(EditorBrowsableState.Never)]
int GetHashCode();
[EditorBrowsable(EditorBrowsableState.Never)]
Type GetType();
}
我尝试在F#中做同样的事情:
type IFluentInterface = interface
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract Equals : (obj) -> bool
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract ToString: unit -> string
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetHashCode: unit -> int
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetType : unit -> Type
end
在我的类型中实现它:
interface IFluentInterface with
member x.Equals(other) = x.Equals(other)
member x.ToString() = x.ToString()
member x.GetHashCode() = x.GetHashCode()
member x.GetType() = x.GetType()
但没有成功。
我还试图覆盖我的类型中的方法并以这种方式添加属性,但这也没有做到。
所以问题仍然存在,我该如何清理我的API?
修改
感谢帮助(见下文),我能够解决我的问题。
总之,.Equals
和.GetHashCode
可以通过[<NoEquality>]
[<NoComparison>]
隐藏,但这也会改变语义。
通过EditorBrowsable属性隐藏不起作用。
拥有干净的API并且仍能够重载方法的唯一方法是使这些方法成员保持静态。
通过在我的项目FSharpSpec内浏览,可以找到生成的课程。
可以找到有问题的类型here.
感谢所有帮助我解决这个问题的人。
干杯......
答案 0 :(得分:5)
从
重复我的回答http://cs.hubfs.net/forums/thread/13317.aspx
在F#中你可以禁止等于&amp;通过使用NoEquality和NoComparison属性注释类型来获取GetHashCode(并从intellisense中删除它们),如下所示。用户定义的方法也可以通过Obsolete属性或带有IsHidden = true的CompilerMessage属性从智能感知列表中隐藏。无法从F#intellisense中隐藏System.Object方法GetType和ToString。
[<NoEquality; NoComparison>]
type Foo() =
member x.Bar() = ()
member x.Qux() = ()
[<System.Obsolete>]
member x.HideMe() = ()
[<CompilerMessage("A warning message",99999,IsError=false,IsHidden=true)>]
member x.WarnMe() = ()
let foo = new Foo()
foo. // see intellisense here
答案 1 :(得分:4)
或者,您可以使用模块中包含的函数使用替代样式设计库。这是在F#中编写功能代码的常用方法,然后您不需要隐藏任何标准的.NET方法。要完成'kvb'给出的示例,以下是面向对象解决方案的示例:
type MyNum(n:int) =
member x.Add(m) = MyNum(n+m)
member x.Mul(m) = MyNum(n*m)
let n = new MyNum(1)
n.Add(2).Mul(10) // 'ToString' shows in the IntelliSense
编写代码的功能方式可能如下所示:
type Num = Num of int
module MyNum =
let create n = Num n
let add m (Num n) = Num (m + n)
let mul m (Num n) = Num (m * n)
MyNum.create 1 |> MyNum.add 2 |> MyNum.mul 10
如果您键入MyNum.
,F#IntelliSense将显示模块中定义的功能,因此在这种情况下您不会看到任何噪音。
答案 2 :(得分:3)
我认为在F#中一般都没有办法做到这一点。在.Equals
和.GetHashCode
的特定情况下,您可以通过在类型上添加[<NoEquality>]
属性使它们无法使用,但除了隐藏这些方法之外,这实际上还具有语义效果。< / p>
修改强>
也许值得一提的是,F#中很少使用流畅的接口,因为使用组合器和流水线更加惯用。例如,假设我们想要创建一种创建算术表达式的方法。而不是
let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)
我认为大多数F#用户更愿意写
open Expressions
let x =
1
|> makeExpr
|> add 2
|> mul 3
|> add 4
使用这种样式,不需要隐藏成员,因为表达式被传递给组合器,而不是调用表达式构建器的方法。