Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 一致地生成对象的哈希_C#_.net_Hash - Fatal编程技术网

C# 一致地生成对象的哈希

C# 一致地生成对象的哈希,c#,.net,hash,C#,.net,Hash,我正在尝试获取对象的哈希(md5或sha) 我已经实现了这一点: 我正在使用nHibernate从数据库检索POCO。 在运行GetHash时,每次从数据库中选择和添加它时,它都是不同的。我想这是意料之中的,因为底层代理将发生变化 反正 有没有办法每次都一致地获取对象上所有属性的哈希值 我曾想过在这个.GetType().GetProperties…..上使用StringBuilder。。。。。在上面创建一个散列,但这似乎效率低下 作为旁注,这是用于跟踪从一个数据库(RDBMS)到NoSQL存

我正在尝试获取对象的哈希(md5或sha)

我已经实现了这一点:

我正在使用nHibernate从数据库检索POCO。
在运行GetHash时,每次从数据库中选择和添加它时,它都是不同的。我想这是意料之中的,因为底层代理将发生变化

反正

有没有办法每次都一致地获取对象上所有属性的哈希值

我曾想过在这个.GetType().GetProperties…..上使用StringBuilder。。。。。在上面创建一个散列,但这似乎效率低下

作为旁注,这是用于跟踪从一个数据库(RDBMS)到NoSQL存储的这些实体的更改
(比较散列值以查看对象是否在rdbms和nosql之间更改)

如果此“散列”仅用于确定实体是否已更改,则以下算法可能会有所帮助(注意,它未经测试,并假设在生成散列时将使用相同的运行时)(否则,“简单”类型对GetHashCode的依赖是不正确的):

GetHashCode()返回一个Int32(不是MD5)

如果使用基本或系统GetHashCode()创建两个具有所有相同属性值的对象,则它们将不会具有相同的哈希值

字符串是一个对象和一个异常

string s1 = "john";
string s2 = "john";
if (s1 == s2) returns true and will return the same GetHashCode()
如果要控制两个对象的相等比较,则应重写GetHash和相等

如果两个对象相同,则它们也必须具有相同的GetHash()。但是具有相同GetHash()的两个对象不一定相同。比较将首先测试GetHash()如果它在那里得到匹配,它将测试Equals。好的,有一些直接到Equals的比较,但是你仍然应该覆盖它们,并确保两个相同的对象生成相同的GetHash

我使用它将客户端与服务器同步。您可以使用所有属性,也可以对VerID进行任何属性更改。这里的优点是更简单、更快的GetHashCode()。在我的例子中,我已经用任何属性更改重置了VerID

    public override bool Equals(Object obj)
    {
        //Check for null and compare run-time types.
        if (obj == null || !(obj is FTSdocWord)) return false;
        FTSdocWord item = (FTSdocWord)obj;
        return (OjbID == item.ObjID && VerID == item.VerID);
    }
    public override int GetHashCode()
    {
        return ObjID ^ VerID;
    }
最后我单独使用了ObjID,这样我就可以做以下事情了

if (myClientObj == myServerObj && myClientObj.VerID <> myServerObj.VerID)
{
   // need to synch
}
if(myClientObj==myServerObj&&myClientObj.VerID myServerObj.VerID)
{
//需要同步吗
}

两个具有相同属性值的对象。它们相等吗?它们是否生成相同的GetHashCode()

personDefault pd1=新personDefault(“John”);
personDefault pd2=新personDefault(“John”);
System.Diagnostics.Debug.WriteLine(po1.GetHashCode().ToString());
System.Diagnostics.Debug.WriteLine(po2.GetHashCode().ToString());
//不同的GetHashCode
if(pd1.Equals(pd2))//返回false
{
System.Diagnostics.Debug.WriteLine(“pd1==pd2”);
}
List personsDefault=新列表();
personsDefault.Add(pd1);
if(personsDefault.Contains(pd2))//返回false
{
System.Diagnostics.Debug.WriteLine(“Contains(pd2)”;
}
personOverRide po1=新personOverRide(“约翰”);
personOverRide po2=新personOverRide(“约翰”);
System.Diagnostics.Debug.WriteLine(po1.GetHashCode().ToString());
System.Diagnostics.Debug.WriteLine(po2.GetHashCode().ToString());
//相同的散列
if(po1.Equals(po2))//返回true
{
System.Diagnostics.Debug.WriteLine(“po1==po2”);
}
List personsOverRide=新列表();
添加(po1);
if(personsOverRide.Contains(po2))//返回true
{
System.Diagnostics.Debug.WriteLine(“包含(p02)”);
}
}
公共类个人过失
{
公共字符串名称{get;private set;}
public personDefault(字符串名){name=name;}
}
公共类personOverRide:对象
{
公共字符串名称{get;private set;}
公共人员权限(字符串名称){name=name;}
公共覆盖布尔等于(对象对象对象)
{
//检查null并比较运行时类型。
如果(obj==null | |!(obj是personOverRide))返回false;
人员超限项目=(人员超限)obj;
返回(Name==item.Name);
}
公共覆盖int GetHashCode()
{
返回Name.GetHashCode();
}
}

如果不重写
GetHashCode
则只继承
对象。GetHashCode
对象。GetHashCode
基本上只返回实例的内存地址,如果它是引用对象。当然,每次加载对象时,它都可能被加载到内存的不同部分,从而导致不同的散列码

这是否是正确的做法还存在争议;但这是“过去”实施的,所以现在不能改变

如果您想要一致的内容,则必须重写
GetHashCode
,并基于对象的“值”(即属性和/或字段)创建代码。这可以像分布式合并所有属性/字段的哈希代码一样简单。也可以像您需要的那样复杂。如果您需要的只是区分两个不同的对象,那么在对象上使用唯一键可能对您有效。如果您要查找更改跟踪,请使用唯一键因为散列可能不起作用

我只是使用字段的所有哈希代码为父对象创建合理分布的哈希代码。例如:

public override int GetHashCode()
{
    unchecked
    {
        int result = (Name != null ? Name.GetHashCode() : 0);
        result = (result*397) ^ (Street != null ? Street.GetHashCode() : 0);
        result = (result*397) ^ Age;
        return result;
    }
}
素数397的使用是为值生成一个唯一的数字,以便更好地分发哈希代码。有关在哈希中使用素数的更多详细信息,请参阅
if (myClientObj == myServerObj && myClientObj.VerID <> myServerObj.VerID)
{
   // need to synch
}
            personDefault pd1 = new personDefault("John");
            personDefault pd2 = new personDefault("John");
            System.Diagnostics.Debug.WriteLine(po1.GetHashCode().ToString());
            System.Diagnostics.Debug.WriteLine(po2.GetHashCode().ToString()); 
            // different GetHashCode
            if (pd1.Equals(pd2))  // returns false
            {
                System.Diagnostics.Debug.WriteLine("pd1 == pd2");
            }
            List<personDefault> personsDefault = new List<personDefault>();
            personsDefault.Add(pd1);
            if (personsDefault.Contains(pd2))  // returns false
            {
                System.Diagnostics.Debug.WriteLine("Contains(pd2)");
            }

            personOverRide po1 = new personOverRide("John");
            personOverRide po2 = new personOverRide("John");
            System.Diagnostics.Debug.WriteLine(po1.GetHashCode().ToString());
            System.Diagnostics.Debug.WriteLine(po2.GetHashCode().ToString());  
            // same hash
            if (po1.Equals(po2))  // returns true
            {
                System.Diagnostics.Debug.WriteLine("po1 == po2");
            }
            List<personOverRide> personsOverRide = new List<personOverRide>();
            personsOverRide.Add(po1);
            if (personsOverRide.Contains(po2))  // returns true
            {
                System.Diagnostics.Debug.WriteLine("Contains(p02)");
            }
        }



        public class personDefault
        {
            public string Name { get; private set; }
            public personDefault(string name) { Name = name; }
        }

        public class personOverRide: Object
        {
            public string Name { get; private set; }
            public personOverRide(string name) { Name = name; }

            public override bool Equals(Object obj)
            {
                //Check for null and compare run-time types.
                if (obj == null || !(obj is personOverRide)) return false;
                personOverRide item = (personOverRide)obj;
                return (Name == item.Name);
            }
            public override int GetHashCode()
            {
                return Name.GetHashCode();
            }
        }
public override int GetHashCode()
{
    unchecked
    {
        int result = (Name != null ? Name.GetHashCode() : 0);
        result = (result*397) ^ (Street != null ? Street.GetHashCode() : 0);
        result = (result*397) ^ Age;
        return result;
    }
}