0

オブジェクトが不変である場合、オブジェクトのディープコピーを作成するのは非常に簡単で効率的です。そのオブジェクトのメモリポインタをコピーするだけです。

また、深い等価性チェックを行うのも非常に簡単で効率的です。ポインタを比較するだけです。

しかし、データが外界からのものであり、そのIDを確認する必要がある場合はどうなりますか?

次の例を検討してください。

  • データベースからの投稿のアプリケーションクエリデータは、不変の投稿オブジェクト(モデル)に逆シリアル化し、メモリにキャッシュします。
  • しばらくすると、アプリケーションは同じデータを再度クエリし、それを不変のPostオブジェクトに逆シリアル化します。
  • では、投稿が変更されたかどうかを確認するにはどうすればよいですか?不変オブジェクトの参照を比較してIDを確認することはできません。参照は異なりますが(データを2回逆シリアル化したため)、データ自体は同じである可能性があります。

そのような状況にどう対処するか?

4

1 に答える 1

1

実行可能である可能性がある、または将来のアプローチのためのより多くのアイデアを提供する可能性がある2つのアプローチ:

  1. 既知の不変インスタンスの1つ以上の辞書を保持し、作成したインスタンスを検索して、それらがまだ辞書にあるかどうかを確認します。その場合は、新しく読み取ったものを辞書インスタンスに置き換えます。オブジェクトが作成されるたびにディクショナリが使用されない限り、参照* equality *を使用して比較を迅速化できますが、参照*inquality*は使用できないことに注意してください。ただし、等しくないアイテムは*通常*異なるハッシュを持つため、オブジェクトにハッシュコードをキャッシュさせると便利な場合があります。また、ある種の「WeakDictionary」を使用しない限り、辞書を定期的にクリーンアップする必要があることにも注意してください(実際には、WeakDictionaryがないと、未使用のアイテムをクリーンアップするのは困難です。少なくとも時々使用済みのものを一掃することなく)。
  2. 各オブジェクトに作成時間インジケーター(おそらく静的な `Interlocked.Increment`カウンター)と、等しいことがわかっている最も古い(最初に作成された)オブジェクトへのリンクを与えることができる場合があります。オブジェクトを比較するときは、「古い既知の等しい」オブジェクトのチェーンをたどってください。チェーンが同じオブジェクトに到達する場合、元のオブジェクトは同じです。それ以外の場合、オブジェクトのハッシュコードが一致する場合は、値が等しいかどうかをテストします。それらが等しい場合は、古いものを指すように新しいもののリンクを更新します。いずれかの開始オブジェクトに複数のリンクのチェーンがある場合、`Interlocked.CompareExchange`は、最も古い既知の等しいオブジェクトを直接指すリンクです。このアプローチを使用すると、値が等しいオブジェクト間の比較により、それらはクリークを形成します。クリーク内の値が等しいオブジェクト間の比較は高速になりますが、異なるクリーク内の値が等しいオブジェクト間の比較により、2つのクリークが1つに結合されます。また、ノード自体への直接リンクではなく、ノードのコンシューマーにラッパーオブジェクトを保持させることが望ましい場合があることにも注意してください。これが行われると、クリーク内のすべてのノードのラッパーが同じ内部データ項目への参照を共有する可能性があります。

適切な辞書タイプが利用できる場合、アプローチ#1はおそらく良い方法ですが、アプローチ#2にもかなりの利点があります。#2の最大の問題は、オブジェクトアクセスに間接参照のレイヤーが追加されることです。それでも、オブジェクトをすばやくクリークに統合できることは、大きなプラスになる可能性があります。

于 2012-11-01T19:01:29.453 に答える