提问人:Mohamad Hammash 提问时间:1/31/2023 更新时间:2/1/2023 访问量:81
Distinct 不适用于 IEquatable<T>
Distinct is not working with IEquatable<T>
问:
我有一个类 Bar,如下所示:
public class Bar : IEquatable<Bar>
{
public string Stringbar1{ get; set; }
public string Stringbar2{ get; set; }
public string Stringbar3{ get; set; }
public string Stringbar4{ get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public EnumFoo1 Enumfoo1{ get; set; }
public bool IsBar{ get; set; }
public List<string> StringBars{ get; set; }
[BsonSerializer(SerializerType = typeof(NullableDateTimeOffsetToUtcSerializer))]
public DateTimeOffset? FooDate{ get; set; }
public string Stringbar5{ get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public EnumFoo2 EnumFoo2 { get; set; }
public string StringBar6{ get; set; }
public int Foo{ get; set; }
public Bar()
{
EnumFoo1= EnumFoo1.Unknown;
EnumFoo2= EnumFoo2.Other;
StringBars= new List<string>();
}
public bool Equals(Bar other)
{
if (other == null)
{
return false;
}
return Stringbar1 == other.Stringbar1&& Stringbar2== other.Stringbar2 && Stringbar3== other.Stringbar3 && Stringbar4== other.Stringbar4 && EnumFoo1== other.EnumFoo1 && IsBar== other.IsBar&& BothNullOrEquals(StringBars,other.StringBars) && StringBar5==other.StringBar5&& FooDate== other.FooDate && ContractType == other.ContractType && LotNumber == other.LotNumber && Rank == other.Rank;
}
public override int GetHashCode()
{
var stringbar1Hashcode = Stringbar1== null ? 0 : Stringbar1.GetHashCode();
var stringbar2HashCode = Stringbar2== null ? 0 : Stringbar2.GetHashCode();
var stringbar3CodeHashCode = Stringbar3== null ? 0 : Stringbar3.GetHashCode();
var EnumFoo1HashCode = EnumFoo1.GetHashCode();
var Stringbar4HashCode = Stringbar4== null ? 0 : Stringbar4.GetHashCode();
var isBarHashCode = IsBar.GetHashCode();
var strtingBarsHashCode = StringBars== null ? 0 : StringBars.GetHashCode();
var stringbar5HashCode = Stringbar5== null ? 0 : Stringbar5.GetHashCode();
var fooDateHashCode = FooDate== null ? 0 : FooDate.GetHashCode();
var enumFoo2HashCode= EnumFoo2.GetHashCode();
var stringBar6HasCode = StringBar6== null ? 0 : StringBar6.GetHashCode();
var fooHashCode= Foo.GetHashCode();
return stringbar1Hashcode ^ stringbar2HashCode ^ stringbar3CodeHashCode ^ EnumFoo1HashCode ^ Stringbar4HashCode ^ isBarHashCode ^ strtingBarsHashCode ^ stringbar5HashCode ^ fooDateHashCode ^ enumFoo2HashCode ^ stringBar6HasCode ^ fooHashCode ;
}
public static bool BothNullOrEquals<T>(IEnumerable<T> left, IEnumerable<T> right)
{
if (left == null && right == null)
{
return true;
}
if (left != null && right != null)
{
return left.SequenceEqual(right);
}
return false;
}
}
Equals 按预期工作,但似乎在 GetHashCode 方面我遗漏了一些东西,因为像 LINQ Distinct 这样的扩展方法没有按预期工作。我知道 Distinct 使用 GetHashCode 方法来比较引用,所以知道我做错了什么吗?
答:
1赞
Dmitry Bychenko
1/31/2023
#1
我能看到的问题是
var strtingBarsHashCode = StringBars== null ? 0 : StringBars.GetHashCode();
请注意,对于 HashCode 是基于引用的:
如果仅共享相同的引用,则哈希码保证相等。但是,您可以通过更轻松的方案来比较这些集合:List<string> StringBars
StringBars
BothNullOrEquals(StringBars, other.StringBars)
因此,不必共享相同的引用即可相等,它们
应该只有相等的项目。请注意,不能为相等的实例返回不同的代码。StringBars
GetHashCode
不要说得太详细;请注意,这应该是对 ;如此有选择性地具有选择性就足够了:GetHashCode
GetHashCode
Equals
2 .. 3
public override int GetHashCode() {
// Let .Net check for null and combine hash codes for you
return HashCode.Combine(Stringbar1, Stringbar2, Stringbar3);
}
编辑:如果你不能使用 ,那就顺其自然吧,但是,请不要把很多字段和属性放到几个最有选择性的字段和属性中:HashCode.Combine
^
GetHashCode
public override int GetHashCode() {
// Let .Net check for null and combine hash codes for you
return (Stringbar1?.GetHashCode() ?? 0) ^
(Stringbar2?.GetHashCode() ?? 0) ^
(Stringbar3?.GetHashCode() ?? 0);
}
评论
0赞
Mohamad Hammash
2/1/2023
不幸的是,该应用程序使用的是不支持此功能的 .netstandard2.0。
评论
GetHashCode
Equals(Object)
GetHashCode
Equals(Object)