インデックス付きプロパティ

順序付けされたデータを抽象化するクラスを定義する場合、基になる実装を公開せずに、そのデータへのインデックス付きアクセスを提供すると役立つことがあります。 これは Item メンバーで実行されます。

構文

式の構文:

// Looking up an indexed property
expr[idx]

/// Assign to an indexed property
expr[idx] <- elementExpr

メンバー宣言の構文:

// Indexed property that can be read and written to
member self-identifier.Item
    with get(index-values) =
        get-member-body
    and set index-values values-to-set =
        set-member-body

// Indexed property can only be read
member self-identifier.Item
    with get(index-values) =
        get-member-body

// Indexed property that can only be set
member self-identifier.Item
    with set index-values values-to-set =
        set-member-body

解説

前の構文の形式では、get メソッドと set メソッドの両方を持つ、get メソッドのみを持つ、または set メソッドのみを持つインデックス付きプロパティを定義する方法が示されています。 get のみに表示される構文と、set のみに表示される構文の両方を組み合わせて、get と set の両方を持つプロパティを生成することもできます。 この後者の形式では、get メソッドと set メソッドに異なるアクセシビリティ修飾子と属性を配置できます。

名前 Item を使用すると、コンパイラでは、プロパティが既定のインデックス付きプロパティとして扱われます。 既定のインデックス付きプロパティは、オブジェクト インスタンスで配列に似た構文を使用してアクセスできるプロパティです。 たとえば、o がこのプロパティを定義する型のオブジェクトである場合、構文 o[index] を使用してプロパティにアクセスします。

既定以外のインデックス付きプロパティにアクセスするための構文では、通常のメンバーと同じように、プロパティの名前とインデックスをかっこで囲んで指定します。 たとえば、o のプロパティが Ordinal と呼ばれる場合、それにアクセスするために o.Ordinal(index) を記述します。

使用する形式に関係なく、インデックス付きプロパティの set メソッドには、常にカリー化された形式を使用する必要があります。 カリー化された関数の詳細については、「関数」を参照してください。

F# 6 以前では、構文 expr.[idx] はインデックスの作成に使用されていました。 オプションの情報警告 (/warnon:3566 またはプロパティ <WarnOn>3566</WarnOn>) をアクティブにし、expr.[idx] 表記の使用の報告を開始できます。

次のコード例は、get および set メソッドを持つ既定および既定以外のインデックス付きプロパティの定義と使用方法を示しています。

type NumberStrings() =
   let mutable ordinals = [| "one"; "two"; "three"; "four"; "five";
                             "six"; "seven"; "eight"; "nine"; "ten" |]
   let mutable cardinals = [| "first"; "second"; "third"; "fourth";
                              "fifth"; "sixth"; "seventh"; "eighth";
                              "ninth"; "tenth" |]
   member this.Item
      with get(index) = ordinals[index]
      and set index value = ordinals[index] <- value
   member this.Ordinal
      with get(index) = ordinals[index]
      and set index value = ordinals[index] <- value
   member this.Cardinal
      with get(index) = cardinals[index]
      and set index value = cardinals[index] <- value

let nstrs = new NumberStrings()
nstrs[0] <- "ONE"
for i in 0 .. 9 do
  printf "%s " nstrs[i]
printfn ""

nstrs.Cardinal(5) <- "6th"

for i in 0 .. 9 do
  printf "%s " (nstrs.Ordinal(i))
  printf "%s " (nstrs.Cardinal(i))
printfn ""

出力

ONE two three four five six seven eight nine ten
ONE first two second three third four fourth five fifth six 6th
seven seventh eight eighth nine ninth ten tenth

複数のインデックス値を持つインデックス付きプロパティ

インデックス付きプロパティには、複数のインデックス値を指定できます。 この場合、プロパティが使用されるときに、値はコンマで区切られます。 このようなプロパティの set メソッドには、2 つのカリー化引数が必要です。最初の引数はキーを含むタプルで、2 番目の引数は設定する値です。

次のコードは、複数のインデックス値を持つインデックス付きプロパティの使用方法を示しています。

open System.Collections.Generic

/// Basic implementation of a sparse matrix based on a dictionary
type SparseMatrix() =
    let table = new Dictionary<(int * int), float>()
    member _.Item
        // Because the key is comprised of two values, 'get' has two index values
        with get(key1, key2) = table[(key1, key2)]

        // 'set' has two index values and a new value to place in the key's position
        and set (key1, key2) value = table[(key1, key2)] <- value

let sm = new SparseMatrix()
for i in 1..1000 do
    sm[i, i] <- float i * float i

関連項目