特別なクラスがあり、それぞれを1つだけWrappedDataTable
に関連付けたいとします。さらに、特定のに対して存在するのは1つだけである必要があります。WrappedDataTable
DataTable
WrappedDataTable
DataTable
同僚は、次のように、自分をキャッシュWrappedDataTable
してファクトリメソッドを使用してアクセスできると提案しました。
public static class DataTableWrapper
{
private Dictionary<DataTable, WrappedDataTable> _wrappedTables;
static DataTableWrapper()
{
_wrappedTables = new Dictionary<DataTable, WrappedDataTable>();
}
public static WrappedDataTable Wrap(this DataTable table)
{
WrappedDataTable wrappedTable;
if (!_wrappedTables.TryGetValue(table, out wrappedTable))
_wrappedTables[table] = wrappedTable = new WrappedDataTable(table);
return wrappedTable;
}
}
辞書のキーは不変の型でなければならないという考えに慣れてきたので、これは最初は非常に疑わしいと思いました。しかし、おそらくこれは必ずしもそうではありませんか?簡単なテストでDataTable
、コンテンツに多数の変更を加えても、コンシステントハッシュコードが維持されているように見えることがわかりました。したがって、aは一貫Dictionary<DataTable, TValue>
して正しい値を返すことができるように見えます。ContainsKey
私が疑問に思っているのは、のベースバージョンがobject.GetHashCode
デフォルトで個々のオブジェクトごとに不変の値を返すのか、それとも私が見ているDataTable
のは単なる幻想なのかということです。
前者が真実であり、object.GetHashCode
問題なく機能する場合、「キーとして不変の型のみを使用する」というアドバイスは、実際には次のようなシナリオにのみ適用されるようです。
- オブジェクトの同等性は、参照の同等性ではなく、ほぼ値の同等性である必要があります。
GetHashCode
タイプのメンバーに基づく独自の実装を持つカスタムタイプがあります。
私のためにこれに光を当てる気になっている賢人はいますか?
更新:私の質問に答えてくれたJonSkeetに感謝します。他のニュースでは、私はいくつかの掘り下げを行い、結局のところアイデンティティ比較を提供するものを思いついたと思いIEqualityComparer<T>
ます!それをチェックしてください(申し訳ありませんが、VB.NETは嫌いです、私はVB.NETプロジェクトを立ち上げたばかりなので、それを書いたのです-翻訳は簡単です):
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices
Public Class IdentityComparer(Of T As Class)
Implements IEqualityComparer(Of T)
Public Overloads Function Equals(ByVal x As T, ByVal y As T) As Boolean _
Implements IEqualityComparer(Of T).Equals
Return Object.ReferenceEquals(x, y)
End Function
Public Overloads Function GetHashCode(ByVal obj As T) As Integer _
Implements IEqualityComparer(Of T).GetHashCode
Return RuntimeHelpers.GetHashCode(obj)
End Function
End Class
このサンプルプログラムを見てください。
Dim comparer As IEqualityComparer(Of String) = New IdentityComparer(Of String)
Dim x As New String("Hello there")
Dim y As New String("Hello there")
Console.WriteLine(comparer.Equals(x, y))
Console.WriteLine(comparer.GetHashCode(x))
Console.WriteLine(comparer.GetHashCode(y))
出力:
誤り 37121646 45592480