假设我有一些特殊的课程 ,WrappedDataTable
并且我想将每个课程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 似乎保持了一致的哈希码;因此, aDictionary<DataTable, TValue>
似乎能够ContainsKey
一致地返回正确的值。
我想知道的是object.GetHashCode
,默认情况下的基本版本是否会为每个单独的对象返回一个不变的值,或者我所看到DataTable
的只是一种错觉?
如果前者是真的——并且object.GetHashCode
工作得很好——那么“只使用不可变类型作为键”的建议似乎真的只适用于以下场景:
- 您希望对象的平等是关于价值平等而不是引用平等,和/或:
- 您有一个自定义类型,它有自己的
GetHashCode
实现,它基于类型的成员。
有哪位大神能帮我解释一下吗?
更新:感谢 Jon Skeet 回答我的问题。在其他新闻中,我做了一些挖掘,并认为我想出了一个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