比较 2 个忽略顺序的对象列表
Comparing 2 lists of objects ignoring order
即使两个列表包含相同的对象,使用 MSTest V2 和 CollectionAssert.AreEquivalent()
也会失败:
// User-defined object
public class ClientDto
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
}
// Test method
var expectedShares = new List<ClientDto>
{
new ClientDto
{
FullName = "Harry Potter",
RentShare = 500m
},
new ClientDto
{
FullName = "Ron Weasley",
RentShare = 300m
},
};
var actualShares = new List<ClientDto>
{
new ClientDto
{
FullName = "Ron Weasley",
RentShare = 300m
},
new ClientDto
{
FullName = "Harry Potter",
RentShare = 500m
},
};
CollectionAssert.AreEquivalent(expectedShares, actualShares);
ClientDto
还有什么需要实现的吗?
因为 class ClientDto
没有实现 IEquatable<ClientDto>
或 IEquatable
,所以使用引用相等来比较实例。
因此,列表中的实例将无法比较 - 即使它们包含相同的数据 - 因为它们的引用不同。
要解决此问题,只需实施 IEquatable<ClientDto>
以便 CollectionAssert.AreEquivalent()
可以正确比较对象:
public class ClientDto: IEquatable<ClientDto>
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
public bool Equals(ClientDto? other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return FullName == other.FullName && RentShare == other.RentShare;
}
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((ClientDto) obj);
}
public override int GetHashCode()
{
unchecked
{
return (FullName.GetHashCode() * 397) ^ RentShare.GetHashCode();
}
}
public static bool operator ==(ClientDto? left, ClientDto? right)
{
return Equals(left, right);
}
public static bool operator !=(ClientDto? left, ClientDto? right)
{
return !Equals(left, right);
}
}
(由 Resharper 提供实施。)
请注意,对于最新版本的 .Net Core 和 C#,您可以使用 record
而不是 class
,因为 record
为您实现了 IEquatable
(以及其他一些东西):
public record ClientDto
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
}
即使两个列表包含相同的对象,使用 MSTest V2 和 CollectionAssert.AreEquivalent()
也会失败:
// User-defined object
public class ClientDto
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
}
// Test method
var expectedShares = new List<ClientDto>
{
new ClientDto
{
FullName = "Harry Potter",
RentShare = 500m
},
new ClientDto
{
FullName = "Ron Weasley",
RentShare = 300m
},
};
var actualShares = new List<ClientDto>
{
new ClientDto
{
FullName = "Ron Weasley",
RentShare = 300m
},
new ClientDto
{
FullName = "Harry Potter",
RentShare = 500m
},
};
CollectionAssert.AreEquivalent(expectedShares, actualShares);
ClientDto
还有什么需要实现的吗?
因为 class ClientDto
没有实现 IEquatable<ClientDto>
或 IEquatable
,所以使用引用相等来比较实例。
因此,列表中的实例将无法比较 - 即使它们包含相同的数据 - 因为它们的引用不同。
要解决此问题,只需实施 IEquatable<ClientDto>
以便 CollectionAssert.AreEquivalent()
可以正确比较对象:
public class ClientDto: IEquatable<ClientDto>
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
public bool Equals(ClientDto? other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return FullName == other.FullName && RentShare == other.RentShare;
}
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((ClientDto) obj);
}
public override int GetHashCode()
{
unchecked
{
return (FullName.GetHashCode() * 397) ^ RentShare.GetHashCode();
}
}
public static bool operator ==(ClientDto? left, ClientDto? right)
{
return Equals(left, right);
}
public static bool operator !=(ClientDto? left, ClientDto? right)
{
return !Equals(left, right);
}
}
(由 Resharper 提供实施。)
请注意,对于最新版本的 .Net Core 和 C#,您可以使用 record
而不是 class
,因为 record
为您实现了 IEquatable
(以及其他一些东西):
public record ClientDto
{
public string FullName { get; set; }
public decimal RentShare { get; set; }
}