比较 2 个对象列表而忽略顺序

时间:2021-06-04 14:59:16

标签: c# mstest

即使两个列表包含相同的对象,使用 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 中实现的吗?

1 个答案:

答案 0 :(得分:1)

因为类 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; }
}
相关问题