gpt4 book ai didi

c# - IEquatable 对象上的 LINQ.Distinct 不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 23:00:39 30 4
gpt4 key购买 nike

我有一个继承自 IEquatable<> 基类的对象。到目前为止一切顺利,它适用于继承相同基类的其他对象。但是我在类“RoomType”上使用“Attrbiutes”属性时似乎存在问题。在下面,您可以看到我期望给出的其他输出的类和测试。

我将问题缩小到 RoomType.GetHashCode() 的问题,当我评论“SafeHashCode(Attributes)”时返回了预期的结果。

测试:

 private static void QuickTest()
{
RoomType[] rooms = new RoomType[] {
new RoomType {
Attributes = new [] { "a", "b,"c"},
},
new RoomType
{
Attributes = new [] { "a", "b","c"},
}
};

List<RoomType> result = rooms.Distinct().ToList();
//result contains 2 items, I was expecting 1
}

房间类型:

public class RoomType : EntityBase
{
public string OriginalRoomCode { get; set; }
public Enum.RoomType RoomCode { get; set; }
public IEnumerable<string> Attributes { get; set; }

public override bool Equals(object obj)
{
RoomType other = obj as RoomType;
if (other != null)
return Equals(other);
return false;
}

public override bool Equals(EntityBase obj)
{
RoomType y = (RoomType)obj;
return SafeEqual(OriginalRoomCode, y.OriginalRoomCode) &&
SafeEqual(RoomCode, y.RoomCode) &&
SafeEqual(Attributes,y.Attributes);
}

public override int GetHashCode()
{
unchecked
{
return SafeHashCode(OriginalRoomCode) ^
SafeHashCode(RoomCode) ^
SafeHashCode(Attributes);
}
}

public override object Clone()
{
return new RoomType
{
RoomCode = (Enum.RoomType)SafeClone(RoomCode),
OriginalRoomCode = (string)SafeClone(OriginalRoomCode),
Attributes = (IEnumerable<string>)SafeClone(Attributes)
};
}
}

实体库:

public abstract class EntityBase : IEquatable<EntityBase>, ICloneable
{
public bool SafeEqual<T>(T x, T y)
{
bool isXDefault = EqualityComparer<T>.Default.Equals(x, default(T));
bool isYDefault = EqualityComparer<T>.Default.Equals(y, default(T));

if (isXDefault && isYDefault)
return true;
if (isXDefault != isYDefault)
return false;

if (x is EntityBase)
return x.Equals(y);

IEnumerable<object> xEnumerable = x as IEnumerable<object>;
IEnumerable<object> yEnumerable = y as IEnumerable<object>;

if (xEnumerable != null && yEnumerable != null)
{
foreach (var yItem in yEnumerable)
{
bool match = false;
foreach (var xItem in xEnumerable)
{
if(SafeEqual(xItem, yItem))
{
match = true;
break;
}
}
if (!match)
return false;
}
return true;
}

return x.Equals(y);
}

public int SafeHashCode<T>(T x)
{
if (EqualityComparer<T>.Default.Equals(x, default(T)))
return 0;



return x.GetHashCode();
}

public object SafeClone<T>(T x)
{
//if x is null or default value
if (EqualityComparer<T>.Default.Equals(x, default(T)))
return default(T);

//if x is of type EntityBase call clone()
if (x is EntityBase)
return (x as EntityBase).Clone();

//else the type is a default type return the value
return x;
}

public abstract bool Equals(EntityBase other);
public override abstract int GetHashCode();

public abstract override bool Equals(object obj);

public abstract object Clone();
}

更新我能够通过在 SafeHashCode(T x) 中添加以下代码来修复它

 IEnumerable<object> xEnumerable = x as IEnumerable<object>;
if (xEnumerable != null)
return xEnumerable.Aggregate(17, (acc, item) => acc * 19 + SafeHashCode(item));

最佳答案

问题是 2 个数组的哈希码不会相同,即使内容可以被认为是相同的。不是将数组传递给 SafeHashCode,而是获取数组每个成员的哈希码。

public override int GetHashCode()
{
unchecked
{
return SafeHashCode(OriginalRoomCode) ^
SafeHashCode(RoomCode) ^
Attributes.Select(x => SafeGetHashCode(x)).Aggregate((seed, current) => seed ^ current);
}
}

关于c# - IEquatable 对象上的 LINQ.Distinct 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43232457/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com