Stephen Swensen
Stephen Swensen

Reputation: 22297

Static Member Indexed Properties

Is it possible to create static member indexed properties in F#? MSDN show them only for instance members, however, I'm able to define the following class:

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

But when I try to use one, I get an error:

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

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

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

I tried a few different syntax variations and none worked. Also weird is that when I hover over set in VS2010 for one of the definitions in the type, I get info about ExtraTopLevelOperators.set.

Upvotes: 3

Views: 804

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243041

If you wanted to recover the Type.Prop.[args] notation, then you can define a simple object to represent an indexable property with the Item property:

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]

This returns a new instance of IndexedProperty every time, so it may be better to cache it. Anyway, I think this is quite nice trick and you can encapsulate some additional behavior into the property type.

A digression: I think that an elegant extension to F# would be to have first-class properties just like it has first-class events. (You could for example create properties that automatically support INotifyPropertyChange with just one line of code)

Upvotes: 5

kvb
kvb

Reputation: 55184

I believe that you call indexed properties using a different syntax (whether instance or static):

ObjWithStaticProperty.StaticPropertyIndexed2(1,2) <- 3

The only semi-exception to this is that an Item property on an instance x can be called via x.[...] (that is, Item is omitted and brackets are used around the arguments).

Upvotes: 4

Related Questions