我已经使用了允许代码生成的 ReSharper 功能一段时间了。我一直这样做的方法是在我的班级中按 Alt-Enter(在任何方法之外),或按 Alt-Ins,然后选择Equality members,然后选择所有成员并单击确定。
这样做时会生成的代码是这样的:
public class Foo
{
public int Bar { get; }
public int Baz { get; }
protected bool Equals(Foo other)
{
return Bar == other.Bar
&& Baz == other.Baz;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Foo) obj);
}
public override int GetHashCode()
{
unchecked
{
return (Bar * 397) ^ Baz;
}
} …
Run Code Online (Sandbox Code Playgroud) 我有这个类,在那里我覆盖了 Object Equals:
public class Foo
{
public string string1 { get; set; }
public string string2 { get; set; }
public string string3 { get; set; }
public override bool Equals(object other)
{
if (!(other is Foo)) return false;
Foo otherFoo = (other as Foo);
return otherFoo.string1 == string1 && otherFoo.string2 == string2 && otherFoo.string3 == string3;
}
}
Run Code Online (Sandbox Code Playgroud)
我收到一个警告“覆盖 object.equals 但不覆盖 object.gethashcode”,我理解覆盖 GetHashCode 的必要性,以便我的类型根据可散列类型进行操作。
据我研究,为了使此代码唯一,通常使用 XOR 运算符,或者涉及素数乘法。所以,根据我的消息来源,来源1和源2我正在考虑我的GesHashCode覆盖方法这两个选项。
1:
public override int GetHashCode() {
return …
Run Code Online (Sandbox Code Playgroud) 对于 NetCore Web APIGET
方法,我需要计算返回的 ETag List<T>
。T 是 a 形式的 DTO record
,仅保存原始类型。
我想计算列表的哈希值。我正在寻找有关如何GetHashCode()
实施的信息,但找不到任何信息。object.GetHashCode()的文档
没有说明有关列表或集合的任何信息。通过代码的结果,我观察到每次运行时相同的列表数据都会创建不同的哈希码。我得出的结论是,GetHashCode()
将指针值用于引用类型项。
GetHashCode()
ofrecord
计算每个成员值的哈希码。因此,我通过循环列表项创建了列表哈希代码:
List<GetGroupsDTO> dtoList = commandResult.Value;
int hash = 17;
foreach(GetGroupsDTO dto in dtoList)
{
hash = hash * 23 + dto.GetHashCode();
}
string eTagPayload = hash.ToString().SurroundWithDoubleQuotes();
Run Code Online (Sandbox Code Playgroud)
List<T>
当然,我不想对每个人都这样做。我想覆盖GetHashCode()
,但我正在努力解决。我不知道如何覆盖通用列表。我可以派生一个新类 DTOList ,我可以在其中重写GetHashCode()
. 但这会导致其他地方变得更加复杂。由于 EFCore Set 查询的结果填充列表,我需要一个自定义转换器,然后需要一个自定义序列化器来返回 Web API 中的列表。
因此,我想知道是否应该为 List 创建一个扩展方法,或者只是一个以 List 作为参数的函数。还有其他选项可以计算 ETag 吗?如何有效计算 DTO 对象列表的 ETag?
我有一个类Person,我必须覆盖它的Equals和GetHashCode方法.如果名称匹配,则两个人对象等于电子邮件匹配.使用相当高效的哈希函数,这样做的好方法是什么?
class Person
{
string Name
string Email
public override Equals(object obj)
{
if (ReferenceEquals(obj, null))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj is Person)
{
Person person = (Person)obj;
return
(this.Name == person.Name)
|| (this.Email == person.Email);
}
return false;
}
public override GetHashCode()
{
// What's a good way to implement?
}
}
Run Code Online (Sandbox Code Playgroud) 我已经创建了一个对象,详细说明.然后我分配:int x = details.GetHashCode();
稍后在程序中,我想使用整数x访问此对象.有没有办法在C#中做到这一点?
非常感谢
保罗
为了确保GetHashCode()方法为对象返回唯一值,我应该遵循哪些规则?
例如:
我创建了一种字符串包装类,并希望将其实例用作与常用字符串互换的字典键.我推翻GetHashCode
,并Equals
找来似乎奇怪的结果.我已经解决了这个问题.请查看我的代码并解释为什么第二次查找返回null.
void Main()
{
var foo = new StringWrapper("foo");
var h = new Hashtable {{ foo, "bar" }};
Console.WriteLine(h["foo"]);
Console.WriteLine(h[foo]); // null ??
}
public class StringWrapper
{
readonly string wrapped;
public StringWrapper(string s) {
wrapped = s;
}
public override bool Equals(object obj) {
return wrapped.Equals(obj);
}
public override int GetHashCode() {
return wrapped.GetHashCode();
}
public override string ToString() {
return wrapped;
}
}
Run Code Online (Sandbox Code Playgroud) 我只有公共字符串属性的简单类.
public class SimpleClass
{
public string Field1 {get; set;}
public string Field2 {get; set;}
public string Field3 {get; set;}
public List<SimpleClass> Children {get; set;}
public bool Equals(SimpleClass simple)
{
if (simple == null)
{
return false;
}
return IsFieldsAreEquals(simple) && IsChildrenAreEquals(simple);
}
public override int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this); //Bad idea!
}
}
Run Code Online (Sandbox Code Playgroud)
对于相等的实例,此代码不返回相同的值.但是这个类没有用于计算哈希的只读字段.
GetHashCode()
如果我的所有属性都是可变的,我怎样才能生成正确的哈希值.
在用于该文档中的"对实施者的说明"部分中GetHashCode
的方法的的IEqualityComparer<T>
接口,它规定:
需要实现以确保如果Equals方法对于两个对象x和y返回true,则x的GetHashCode方法返回的值必须等于为y返回的值.
众所周知,为什么你希望两个实例T
在两个项相等的情况下返回相同的哈希码; 他们不同意味着他们不平等,而他们是相同意味着他们可能是平等的.
当两个实例不相等时,我将引用解释为未定义的返回值(即使它们的值可能表示如此).
以下面的例子为例.我有一个序列int?
我想用于统计分类,其中每个非null int?
表示一个类的属性(想想枚举值).在这些值为空的情况下,您不希望将值视为相等,因为它们会将训练集偏向缺失值.如果有的话,在这种情况下,当与其他空值比较时,您将需要空值以返回false.
问题是,在GetHashCode
方法中,当给出null时,我可能想要返回0(或者其他一些数字,也许Int32.MinValue
).现在,我知道当使用此IEqualityComparer<T>
实现键入任何内容时,检查字典中是否存在键的性能对于这些情况不是最佳的.
也就是说GetHashCode
,当调用Equals
返回false 时,返回已知冲突的值为其他值时是否有效?我倾向于是,因为上面的引用在这个问题上是不确定的.