首页 文章

一次性声明静态和实例成员的惯用方法?

提问于
浏览
3

当我使用新函数扩展类型时,我通常希望它可以从点表示法和自由表单中获得 . 根据具体情况,两者都可以更具可读性,前者有助于智能感知,而后者有助于理解 .

在C#/ VB.net中,扩展方法执行此操作(尽管我不能将函数限制为扩展静态类的静态方法,如F#中所示) . 我可以编写一次函数然后以两种方式调用它:

<Extension>
public function bounded(s as string, min as UShort, max as UShort) as string
    if min > max then throw new ArgumentOutOfRangeException
    if string.IsNullOrEmpty(s) then return new string(" ", min)
    if s.Length < min then return s.PadRight(min, " ")
    if s.Length > max then return s.Substring(0, max)
    return s
end function

' usage     
dim b1 = bounded("foo", 10, 15)
dim b2 = "foo".bounded(0, 2)

('s not quite perfect yet, as I'喜欢 boundedString 的静态方法,但C#/ VB.Net不能这样做 . 在这方面指向F# . )

在F#中,另一方面,我必须将该函数与该方法分开声明:

// works fine
[<AutoOpen>]
module Utilities = 
    type List<'T> with
            member this.tryHead = if this.IsEmpty then None else Some this.Head        
    module List =             
        let tryHead (l : List<'T>)  = l.tryHead

问题: Is there a more elegant way to declare both methods at once?

我试着用:

// doesn't quite work
type List<'T> with        
    member this.tryHead = if this.IsEmpty then None else Some this.Head
    static member tryHead(l : List<'T>) = l.tryHead

至少会让我跳过模块声明,但是当定义编译时,它不太有用 - someList.tryHead 没问题,但 List.tryHead someList 会导致 Property tryHead is not static 错误 .

Bonus question :如您所见,静态成员定义需要类型注释 . 但是,没有其他类型可以访问刚刚定义的方法 . 那么,为什么不能推断这种类型呢?

1 回答

  • 3

    我不知道在一行代码中声明两个API的方法,但是你可以通过使函数成为实现来摆脱类型注释,然后定义函数术语的方法:

    [<AutoOpen>]
    module Utilities = 
        module List =
            let tryHead l = if List.isEmpty l then None else Some (List.head l)
        type List<'a> with
            member this.tryHead = List.tryHead this
    

相关问题