我正在尝试获取对象的哈希值(md5或sha).
我实现了这个:http: //alexmg.com/post/2009/04/16/Compute-any-hash-for-any-object-in-C.aspx
我正在使用nHibernate从数据库中检索我的POCO.
在此运行GetHash时,每次从数据库中选择并保湿时都会有所不同.我想这是预期的,因为底层代理会改变.
无论如何,
有没有办法在对象上获取所有属性的哈希值,每次都是一致的?
我已经玩弄了使用StringBuilder而不是this.GetType().GetProperties .....并在其上创建哈希,但这似乎效率低下的想法?
作为旁注,这是用于将这些实体从一个数据库(RDBMS)更改跟踪到NoSQL存储(比较哈希值以查看rdbms和nosql之间是否更改了对象)
如果您使用 Visual Studio 自己的重构菜单将 GetHashCode 实现添加到这样的类:
并选择类中唯一的 int 属性:
它在 .NET Framework 上生成此代码:
public override int GetHashCode()
{
return -1937169414 + Value.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
(它HashCode.Combine(Value)在 .NET Core 上生成,我不确定它是否涉及相同的值)
这个值有什么特别之处?为什么不Value.GetHashCode()直接使用Visual Studio ?据我了解,它并没有真正影响哈希分布。由于它只是加法,连续的值仍然会累积在一起。
编辑:我只在不同的类中尝试过这个,Value但显然属性名称会影响生成的数字。例如,如果您将属性重命名为Halue,则数字变为 387336856。感谢 Gökhan Kurt 指出这一点。
我有一个案例,我需要抓取一堆不同的项目,但我的源是一个具有两个属性的对象的集合,如下所示:
public class SkillRequirement
{
public string Skill { get; set; }
public string Requirement { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我尝试获得如下集合:
SkillRequirementComparer sCom = new SkillRequirementComparer();
var distinct_list = source.Distinct(sCom);
Run Code Online (Sandbox Code Playgroud)
我试图为此实现一个IEqualityComparer<T>,但我对这个GetHashCode()方法感到难过.
Comparer的类:
public class SkillRequirementComparer : IEqualityComparer<SkillRequirement>
{
public bool Equals(SkillRequirement x, SkillRequirement y)
{
if (x.Skill.Equals(y.Skill) && x.Requirement.Equals(y.Requirement))
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(SkillRequirement obj)
{
//?????
}
}
Run Code Online (Sandbox Code Playgroud)
通常我会GetHashCode()在一个属性上使用,但因为我在两个属性上进行比较,所以我有点不知所措.我做错了什么,或者遗漏了一些非常明显的东西?
如果没有为引用类型做任何特殊操作,则Equals()意味着引用相等(即相同的对象).如果我选择覆盖Equals()引用类型,它是否总是意味着两个对象的值是等价的?
考虑这个可变性 Person类:
class Person
{
readonly int Id;
string FirstName { get; set; }
string LastName { get; set; }
string Address { get; set; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
表示完全相同的人的两个对象将始终具有相同的Id,但是其他字段可能随时间不同(即,在地址改变之前/之后).
对于这个对象,Equals可以定义为不同的东西:
Ids相等(代表同一个人但具有不同地址的两个对象将返回true)问题:这个课程中哪些(如果有的话)更适合?(或许问题应该是,"这个班级的大多数客户如何期望Equals()表现?")
笔记:
Hashsetor中使用这个类更加困难Dictionary使用Identity Equality使得Equals和=运算符之间的关系变得奇怪(即在检查两个Person对象(p1和p2)之后返回true)Equals(),您可能仍然希望更新引用以指向"较新的"Person对象,因为它是不等值).例如,以下代码读取奇怪 - 似乎它什么都不做,但它实际上是删除p1并添加p2:
HashSet<Person> people = new HashSet<Person>();
people.Add(p1);
// ... p2 is an new object that has the same Id as p1 …Run Code Online (Sandbox Code Playgroud)什么构成了GetHashCode方法的良好实现?我做了一些谷歌搜索,并找到了一些好线(MSDN),但似乎逻辑只是操纵存储为类中的字段的两个数字.这个方法实际逻辑是否这么简单?
我需要覆盖由三个字符串组成的类型的GetHashCode方法.这是我的代码:
protected override int GetHashCode()
{
return str1.GetHashCode() + str2.GetHashCode() + str3.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
这种方法实现的安全方法是什么?
我正在研究如何为类构建最好的HashCode,我看到了一些算法.我看到了这一个:Hash Code实现,似乎是.NET类HashCode方法类似(通过反映代码看).
所以问题是,为什么不创建上面的静态类以便自动构建HashCode,只需传递我们认为是"键"的字段.
// Old version, see edit
public static class HashCodeBuilder
{
public static int Hash(params object[] keys)
{
if (object.ReferenceEquals(keys, null))
{
return 0;
}
int num = 42;
checked
{
for (int i = 0, length = keys.Length; i < length; i++)
{
num += 37;
if (object.ReferenceEquals(keys[i], null))
{ }
else if (keys[i].GetType().IsArray)
{
foreach (var item in (IEnumerable)keys[i])
{
num += Hash(item);
}
}
else
{
num += keys[i].GetHashCode();
}
}
}
return …Run Code Online (Sandbox Code Playgroud) HashSet<T>.Add首先比较结果GetHashCode.如果它们是相同的,它会调用Equals.
现在,我的理解是为了实现GetHashCode,必须用对象的字段来完成某些事情.一个简单的示例实现可以在被覆盖的System.Object.GetHashCode的最佳算法是什么?.
在我的测试中,在填充随机数据的1.000.000对对象上进行比较,两者之间的性能或多或少相等.GetHashCode在链接示例中实现,Equals只需调用Equals所有字段.那么为什么要用GetHashCode它Equals?
在C#中为类创建自己的GetHashCode方法的最佳方法是什么?假设我有一个简单的类(它覆盖了Equals方法),如下所示:
class Test
{
public string[] names;
public double[] values;
public override bool Equals(object obj)
{
return (obj is Test) && this.Equals((Test)obj);
}
public bool Equals(Test t)
{
return names.Equals(t.names) && values.Equals(t.values);
}
}
Run Code Online (Sandbox Code Playgroud)
我应该使用GetHashCode方法的默认代码吗?
public override int GetHashCode()
{
return base.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
我应该将该方法基于我班级的内容吗?
public override int GetHashCode()
{
return names.GetHashCode() + values.GetHashCode() ;
}
Run Code Online (Sandbox Code Playgroud)
或者我应该做些什么?
在这篇MSDN文章 http://msdn.microsoft.com/en-us/library/ms132123.aspx中, 它讨论了Class Equalitycomparer并有一个例子.在这个关于比较它的例子中它有这个类 -
class BoxSameDimensions : EqualityComparer<Box>
{
public override bool Equals(Box b1, Box b2)
{
if (b1.Height == b2.Height & b1.Length == b2.Length
& b1.Width == b2.Width)
{
return true;
}
else
{
return false;
}
}
public override int GetHashCode(Box bx)
{
int hCode = bx.Height ^ bx.Length ^ bx.Width;
return hCode.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白行hCode = bx.Height ^ bx.Length ^ bx.Width;
有人可以解释一下吗?为什么xor?