比如说我有一些特殊的课程,
WrappedDataTable
我想把每一个
包装数据表
恰好一
DataTable
. 此外,我希望有不止一个
可擦除数据的
存在于任何给定的
可计算的
.
A colleague suggested I could cache my
包装数据表
并使用工厂方法访问一个,如下所示:
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;
}
}
一开始我觉得这很可疑,因为我已经熟悉字典中的键应该是不可变的类型。但也许情况并非如此?一个快速的测试告诉我
可计算的
在对其内容进行多次修改的过程中,似乎保持了一致的哈希代码;a
Dictionary<DataTable, TValue>
因此,似乎能够返回正确的值。
ContainsKey
一贯地。
我想知道的是基础版本
object.GetHashCode
默认情况下,将返回每个对象的不变值,或者如果我看到的是
可计算的
只是一种幻觉?
如果前者是真的
object.GetHashCode
工作得很好——似乎“只使用不可变类型作为键”的建议实际上只适用于以下情况:
-
You want equality of objects to be about value equality as opposed to reference equality, and/or:
-
您有自己的自定义类型
GetHashCode
基于类型成员的实现。
外面有什么圣人关心我吗?
更新
感谢乔恩·斯基特回答我的问题。在另一个新闻里,我做了一些挖掘,认为我想出了一个
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
Take a look at this example program:
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))
输出:
False
37121646
45592480