1

null許容型ではない配列が渡されたときはいつでも、それがnullかどうかを確認する必要があることを意味しますか?実際にはチェックすることさえできません<> nullが、使用する必要がoperator.uncheckedあります。C#よりも優れていますか?

type test=
    {
        value: int
    }

let solution = Array.zeroCreate 10

solution.[0] <- {value = 1}
solution.[1].value   // System.NullReferenceException: Object reference not set to an instance of an object

type test =
  {value: int;}
val solution : test [] =
  [|{value = 1;}; null; null; null; null; null; null; null; null; null|]
val it : unit = ()
4

3 に答える 3

3

配列がどこから渡されるかによって異なります。

配列が作成され、F#内でのみ使用される場合は、いいえ、nullをチェックする必要はありません。実際、F#コンパイラはコンパイルされたILのようにそれらを表すことによって、 (場合によっては)のようないくつかの特別な値を最適化するため、 nullを(を使用して)チェックするべきではありません。Unchecked.defaultOf[]Nonenull

別の言語(C#など)で記述されたコードによって渡される配列を使用している場合は、はい、それでもnullをチェックする必要があります。呼び出し元のコードが配列を作成するだけで、それ以上配列を変更しない場合は、nullチェックを1回だけ実行する必要があります。

編集:これは、F#コンパイラが特定の値の表現を最適化する方法についての以前の議論ですnullなぜNoneはnullとして表されないのですか?

于 2012-12-16T15:13:23.513 に答える
2

のドキュメントがArray.zeroCreate示すように、要素をに初期化しますUnchecked.defaultof<_>。したがって、これには、直接使用する場合と同じ注意事項がすべて含まれUnchecked.defaultofています。一般的に、私のアドバイスは、可能な限り Array.create/を使用し、可能なパフォーマンスの最適化として扱うことです(null許容でない型を処理する場合は常に注意が必要です)。Array.initArray.zeroCreate

于 2012-12-17T07:14:09.477 に答える
1

クラスとして実装されているレコード型を作成していますが、これは実際にはnull可能です。構造体を作成する場合、コードは次のようになります。

type test =
    struct
        val value: int
        new(v) = { value = v }
        override x.ToString() = x.value.ToString()
    end

let solution = Array.zeroCreate 10

solution.[0] <- test(1)

これは以下を出力します:val solution : test [] = [|1; 0; 0; 0; 0; 0; 0; 0; 0; 0|]

Struct属性を使用して型を記述し、インデントのレベルを節約することもできます。

[<Struct>]
type test =
    val value: int
    new(v) = { value = v }
    override x.ToString() = x.value.ToString()
于 2012-12-16T13:47:20.220 に答える