2

データベースから一意のアイテムを取得する場合、クライアントから提供された ID のデータがない場合のシナリオに対応する必要があります。たとえば、ID が正しくないか、キャッシュされたデータの有効期限が切れています。

この例で使用している特定の DB クライアント ライブラリは ServiceStack.Redis ですが、原則はどの CLR ライブラリにも当てはまると思います。

以下に示すレコード タイプを使用してデータ構造を定義しました。現在、クライアント ライブラリを使用してデータベースに存在しないキーのデータを取得すると、null値が返されます。これは、私は期待し、満足しています。問題は、実行時に発生する可能性があるにもかかわらず、F# コンパイラがこのシナリオのパターン マッチを許可しないことです。

type MyRecordType = { id:int; name:string; desc:string }

let redis = new RedisClient("localhost")
let nullCheck =
    let item = redis.Get<MyRecordType> "xxx"
    // it is possible that item is null
    // but the compiler will not permit the match
    match item with
    | null -> None
    | _ -> Some item

Redis クライアント ライブラリには、ブール値を返す 'ContainsKey' メソッドが含まれています。これを最初に使用できますが、ここではデータベースへの 2 つの呼び出しは不要です。もう 1 つの方法は、C# プロジェクトで定義されたクラスをデータ構造として使用することですが、これにはオーバーヘッドがかかりすぎます。この属性は、 での一致も許可しませんnull

非常に一般的な問題のように思われるため、このシナリオに対処するために使用する規則を知りたいですか?

4

3 に答える 3

4

ボクシングを利用したこの記事も見つけました。少しきれいに読めると思います:

if (box item = null) then None else Some item
于 2014-01-15T00:08:41.633 に答える
4

AllowNullLiteral残念ながら、レコードには使用できません。結果として、最善の解決策は、null 値を作成し、そのように等値チェックを行うことです。

if item = Operators.Unchecked.defaultof<_> then None else Some(item)
于 2014-01-14T23:40:30.687 に答える
3

これは、私が見た他のオプションよりも少しパフォーマンスが良いと思います。F# の equals 演算子は非常に強力ですが、null 参照があるかどうかだけを本当に知りたい場合は、かなりやり過ぎです。

if obj.ReferenceEquals(item, null) then None else Some item

多くの比較をしない限り問題にならないかもしれませんが、実際には次のような違いがあります。

> for i = 1 to 100000000 do bar = null |> ignore;;
Real: 00:00:00.233, CPU: 00:00:00.234, GC gen0: 0, gen1: 0, gen2: 0
val it : unit = ()
> for i = 1 to 100000000 do obj.ReferenceEquals(bar, null) |> ignore;;
Real: 00:00:00.030, CPU: 00:00:00.031, GC gen0: 0, gen1: 0, gen2: 0
于 2014-01-16T17:46:46.597 に答える