静态成员索引属性

时间:2011-03-23 04:28:05

标签: f#

是否可以在F#中创建静态成员索引属性? MSDN仅为实例成员显示它们,但是,我可以定义以下类:

type ObjWithStaticProperty =
    static member StaticProperty
        with get () = 3
        and  set (value:int) = ()

    static member StaticPropertyIndexed1
        with get (x:int) = 3
        and  set (x:int) (value:int) = ()

    static member StaticPropertyIndexed2
        with get (x:int,y:int) = 3
        and  set (x:int,y:int) (value:int) = ()

//Type signature given by FSI:
type ObjWithStaticProperty =
  class
    static member StaticProperty : int
    static member StaticPropertyIndexed1 : x:int -> int with get
    static member StaticPropertyIndexed2 : x:int * y:int -> int with get
    static member StaticProperty : int with set
    static member StaticPropertyIndexed1 : x:int -> int with set
    static member StaticPropertyIndexed2 : x:int * y:int -> int with set
  end

但是当我尝试使用一个时,我收到一个错误:

> ObjWithStaticProperty.StaticPropertyIndexed2.[1,2] <- 3;;

  ObjWithStaticProperty.StaticPropertyIndexed2.[1,2] <- 3;;
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error FS1187: An indexer property must be given at least one argument

我尝试了一些不同的语法变体,但都没有。同样奇怪的是,当我将鼠标悬停在VS2010中的set上以获取该类型中的一个定义时,我会获得有关ExtraTopLevelOperators.set的信息。

2 个答案:

答案 0 :(得分:5)

如果要恢复Type.Prop.[args]表示法,则可以定义一个简单对象来表示具有Item属性的可索引属性:

type IndexedProperty<'I, 'T>(getter, setter) =
  member x.Item 
    with get (a:'I) : 'T = getter a
    and set (a:'I) (v:'T) : unit = setter a v

type ObjWithStaticProperty =
    static member StaticPropertyIndexed1 = 
      IndexedProperty((fun x -> 3), (fun x v -> ()))

ObjWithStaticProperty.StaticPropertyIndexed1.[0]

每次都会返回IndexedProperty的新实例,因此最好将其缓存。无论如何,我认为这是一个非常好的技巧,你可以将一些额外的行为封装到属性类型中。

一个题外话:我认为对F#的一个优雅扩展就是拥有一等属性,就像它有一流的事件一样。 (例如,您可以创建仅使用一行代码自动支持INotifyPropertyChange的属性)

答案 1 :(得分:4)

我相信您使用不同的语法(无论是实例还是静态)调用索引属性:

ObjWithStaticProperty.StaticPropertyIndexed2(1,2) <- 3

唯一的例外是,Item实例上的x属性可以通过x.[...]调用(即省略Item,括号为围绕参数使用。)