[英]GetHashCode returns the same value for different objects. Is there any method to identify object by particular properties?
我正在嘗試創建一個hashcode方法。 我有如下代碼:
private static object GetValue<T>(object item, string propertyName)
{
ParameterExpression arg = Expression.Parameter(item.GetType(), "x");
Expression expr = Expression.Property(arg, propertyName);
UnaryExpression unaryExpression = Expression.Convert(expr, typeof(object));
var propertyResolver = Expression.Lambda<Func<T, object>>(unaryExpression, arg).Compile();
return propertyResolver((T)item);
}
private static int GetHashCode<T>(T obj, List<string> columns)
{
unchecked
{
int hashCode = 17;
for (var i = 0; i < columns.Count; i++)
{
object value = GetValue<T>(obj, columns[i]);
var tempHashCode = value == null ? 0 : value.GetHashCode();
hashCode = (hashCode * 23) + tempHashCode;
}
return hashCode;
}
}
private static void TestHashCode()
{
var t1 = new { ID = (long)2044716, Type = "AE", Method = (short)1022, Index = 3 };
var t2 = new { ID = (long)12114825, Type = "MEDAPE", Method = (short)1700, Index = 2 };
var e1 = t1.GetHashCode();
var e2 = t2.GetHashCode();
var columns = new[] { "ID", "Type", "Method", "Index" }.ToList();
var k1 = GetHashCode(t1, columns);
var k2 = GetHashCode(t2, columns);
}
e1值為-410666035,e2值為101205027。k1值為491329214。k2值為491329214。
HashCode步驟:
hashCode = 17
tempHashCode = 2044716
哈希碼= 2045107
tempHashCode = 1591023428
哈希碼= 1638060889
tempHashCode = 66978814
哈希碼= -912326403
tempHashCode = 3
哈希碼= 491329214
k1和k2為何值相同? 因為默認的.net gethashcode方法提供了兩個不同的值。 我想創建一個可以獲取列列表的哈希碼方法。 我想通過特定屬性創建一個哈希碼。 我正在嘗試通過特定屬性為對象獲取唯一值。
如果GetHashCode不保證唯一值,如何通過特定屬性識別對象?
我懷疑問題是由您的GetHashCode<T>
方法中的value.GetHashCode()
引起的。 該值變量在那里是一個對象,我認為GetHashCode()
不會返回您期望的結果。 嘗試調試以找出正在發生的情況。
您可能想嘗試保留代碼,但請使用RuntimeHelpers.GetHashCode()
(來自命名空間System.Runtime.CompilerServices
)來代替Object.GetHashCode()
)。
此處的完整參考資料: https : //docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.runtimehelpers.gethashcode?redirectedfrom=MSDN&view=netframework-4.7.2#System_Runtime_CompilerServices_RuntimeHelpers_GetHashCode_System_Object_
祝好運!
GetHashCode
返回與實現相關的值。 其特殊的設計適合“標准”使用,並且僅在應用程序的生命周期內才有意義。 默認算法並非旨在避免沖突。
GetHashCode
方法並非每個實例都唯一。
您的方法依賴於每列哈希的組成。 哈希碼必須滿足某些要求,例如域中的分布。 但是,不能保證該組合物保留這些屬性和要求:添加的列越多,沖突可能就越“陌生”。
另外,您正在調用value.GetHashCode()
,這會阻止裝箱操作。 如johey所建議,您應該使用RuntimeHelpers.GetHashCode()
方法,因為它在計算哈希值之前會將對象解釋為值。
.NET數據結構旨在內部處理沖突,例如, IDictionary
使用哈希值選擇存儲桶,然后依次掃描該存儲桶。
我想在這里寫我的解決方案。 所有的說法都是正確的,但並非完全正確。 我想在這里收集話題。
GetHashCode
始終為相同的對象提供相同的值。 GetHashCode
的值始終可能不屬於不同的對象。
因此,首先比較GetHashCode
的值以提高性能,然后如果GetHashCode
值相同,則進行下一步比較對象。
我創建了一個IEqualityComparer。
private class CustomEqualityComparer<T> : IEqualityComparer<T>
{
private readonly List<string> _columns;
private readonly bool _enableHashCode;
private readonly ConcurrentDictionary<string, Func<T, object>> _cache;
public CustomEqualityComparer(List<string> columns, ConcurrentDictionary<string, Func<T, object>> cache, bool enableHashCode = false)
{
_columns = columns;
_enableHashCode = enableHashCode;
_cache = cache;
}
public bool Equals(T x, T y)
{
for (var i = 0; i < _columns.Count; i++)
{
object value1 = GetValue(x, _columns[i], _cache);
object value2 = GetValue(y, _columns[i], _cache);
if (!value1.Equals(value2)) return false;
}
return true;
}
public int GetHashCode(T obj)
{
return _enableHashCode ? GetHashCode(obj, _columns, _cache) : 0;
}
private object GetValue(object item, string propertyName, ConcurrentDictionary<string, Func<T, object>> cache)
{
if (!cache.TryGetValue(propertyName, out Func<T, object> propertyResolver))
{
ParameterExpression arg = Expression.Parameter(item.GetType(), "x");
Expression expr = Expression.Property(arg, propertyName);
UnaryExpression unaryExpression = Expression.Convert(expr, typeof(object));
propertyResolver = Expression.Lambda<Func<T, object>>(unaryExpression, arg).Compile();
cache.TryAdd(propertyName, propertyResolver);
}
return propertyResolver((T)item);
}
private int GetHashCode(T obj, List<string> columns, ConcurrentDictionary<string, Func<T, object>> cache)
{
unchecked
{
var hashCode = 17;
for (var i = 0; i < columns.Count; i++)
{
object value = GetValue(obj, columns[i], cache);
var tempHashCode = value == null ? 0 : value.GetHashCode();
hashCode = hashCode * 23 + tempHashCode;
}
return hashCode;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.