【问题标题】:Static Member Indexed Properties静态成员索引属性
【发布时间】:2011-03-23 04:28:04
【问题描述】:

是否可以在 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 的信息。

【问题讨论】:

    标签: f#


    【解决方案1】:

    如果您想恢复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 的属性)

    【讨论】:

      【解决方案2】:

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

      ObjWithStaticProperty.StaticPropertyIndexed2(1,2) <- 3
      

      唯一的半例外是实例x 上的Item 属性可以通过x.[...] 调用(也就是说,Item 被省略,并且在参数周围使用括号)。

      【讨论】:

      • 所以x.[...] 语法只在实例上有效?
      • @Stringer - 它比这更具体 - 它仅对名为“Item”的实例属性有效。
      • @Stringer 实际上,它对类型的System.Reflection.DefaultMemberAttribute 命名的任何实例属性都有效。如果该类型未使用该属性进行修饰,则默认为Item。示例:[&lt;System.Reflection.DefaultMember("Foo")&gt;] type C() = member x.Foo with get i = i;; let three = C().[3];;
      猜你喜欢
      • 1970-01-01
      • 2018-05-31
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多