C# 比较两个列表<;T>;使用XUnit断言函数

C# 比较两个列表<;T>;使用XUnit断言函数,c#,assert,xunit,xunit.net,xunit2,C#,Assert,Xunit,Xunit.net,Xunit2,以下内容不适用于XUnit(StartDate和EndDate是DatePeriod仅有的两个公共属性): var实际值=新列表() { new DatePeriod(){StartDate=new DateTime(2017,1,20),EndDate=new DateTime(2018,1,19)}, new DatePeriod(){StartDate=new DateTime(2018,1,20),EndDate=new DateTime(2018,3,31)} }; var预期值=新列

以下内容不适用于XUnit(StartDate和EndDate是DatePeriod仅有的两个公共属性):

var实际值=新列表()
{
new DatePeriod(){StartDate=new DateTime(2017,1,20),EndDate=new DateTime(2018,1,19)},
new DatePeriod(){StartDate=new DateTime(2018,1,20),EndDate=new DateTime(2018,3,31)}
};
var预期值=新列表()
{
new DatePeriod(){StartDate=new DateTime(2017,1,20),EndDate=new DateTime(2018,1,19)},
new DatePeriod(){StartDate=new DateTime(2018,1,20),EndDate=new DateTime(2018,3,31)}
};
断言。相等(实际、预期);
根据一些研究,我希望在最新版本的XUnit中,只要顺序与实际相同,就可以认为它们是相等的。

List
元素间不检查相等性

使用LINQ的方法检查您的相等性

var equal = actual.SequenceEqual(expected);
并在对象上实现
IEquatable

public class DatePeriod : IEquatable<DatePeriod>
{
     public DateTime StartDate { get; set; }
     public DateTime EndDate { get; set; }

     public bool Equals(Period other)
     {
         return StartDate == other.StartDate && EndDate == other.EndDate;
     }
}
public类DatePeriod:IEquatable
{
公共日期时间起始日期{get;set;}
公共日期时间结束日期{get;set;}
公共bool等于(其他期间)
{
返回StartDate==other.StartDate&&EndDate==other.EndDate;
}
}

为了安全起见,请检查是否存在空值。有关更完整的实现,请参见Yacoub的答案。

您只需覆盖
Equals
GetHashCode
,如下所示:

public class DatePeriod
{
    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;

        DatePeriod other = (DatePeriod)obj;

        return StartDate.Equals(other.StartDate) && EndDate.Equals(other.EndDate);
    }

    public override int GetHashCode()
    {
        return new {StartDate, EndDate}.GetHashCode();
    }

    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}
xUnit识别集合的意义在于您可以调用
Assert.Equal
,而其他测试框架则需要特殊的方法,如
CollectionAssert.AreEqual


在所有情况下,框架都会为列表中的每个项调用
Equals
,并从另一个列表中传递相应的项。如果您有一个字符串或整数列表,那么默认情况下,
Equals
是正确实现的。对于像
DatePeriod
这样的自定义对象,
Equals
方法的默认实现基于引用相等,即两个对象相等,因为它们实际上是相同的对象。要获得基于值的相等,您必须重写
Equals
方法(以及推荐的
GetHashCode
方法)。

期间定义的
Equals
GetHashCode
方法吗?不,这是我需要做的吗?@YacoubMassad请查看我对您答案的评论,我不得不稍微更新我的帖子,因为没有句点对象,所有的东西都使用DatePeriod。嘿,这似乎正是我需要的,但是你能看看我最近对帖子的更新吗。我很抱歉,因为没有句号这样的对象。一切都使用DatePeriod。@BlakeRivell您最初有一个列表,其中包含一系列句点,这使Yacoub相信句点子类DatePeriod。@Theanatherma是正确的,这就是为什么我试图让他知道我在评论中的错误,并问他是否可以更新他的答案。否,有时我使用它是因为我有一个自定义的比较逻辑,它不是对象本身固有的。例如,我只想通过
ID
比较一些情况,而不想比较其他属性。例如,当您创建一个
字典
时,您可以传递这样的自定义比较器。如果有一种“标准”方法来比较对象,那么您应该将这样的比较逻辑放在对象本身上。如果比较逻辑是自定义的,则将其放在自定义对象中(实现
IEqualityComparer
)。
public class DatePeriod
{
    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;

        DatePeriod other = (DatePeriod)obj;

        return StartDate.Equals(other.StartDate) && EndDate.Equals(other.EndDate);
    }

    public override int GetHashCode()
    {
        return new {StartDate, EndDate}.GetHashCode();
    }

    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}