为什么这些相同的结果无法通过 AreEqual 和 AreSame 测试断言?

Why do these identical results fail the AreEqual and AreSame test assertions?

我有这个测试代码:

[TestMethod]
public void TestGetDatesForNthDOWOfMonth()
{
    List<DateTime> firstFridaysInFirstQuarterOf2017 = new List<DateTime>();
    // These were determined by looking at a calendar
    firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 1, 6));
    firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 2, 3));
    firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 3, 3));
    DayOfWeek dow = DayOfWeek.Friday;
    DateTime startDate = new DateTime(2017, 1, 1);
    DateTime endDate = new DateTime(2017, 3, 31);
    List<DateTime> testFirstFridaysInFirstQuarterOf2017 = RoboReporterConstsAndUtils.GetDatesForNthDOWOfMonth(startDate, endDate, dow, 1);
    //Assert.AreEqual(firstFridaysInFirstQuarterOf2017, testFirstFridaysInFirstQuarterOf2017);
    Assert.AreSame(firstFridaysInFirstQuarterOf2017, testFirstFridaysInFirstQuarterOf2017);
}

被测方法为:

internal static List<DateTime> GetDatesForNthDOWOfMonth(
    DateTime startDate,
    DateTime endDate,
    DayOfWeek dayOfWeek,
    int ordinal)
{
    var foundDates = new List<DateTime>();
    // Make sure ordinal parameter is within the allowable range
    //If it's too high, set it to 5 (last week) so it returns the last
    // qualifying day of each month
    ordinal = Math.Min(Math.Max(ordinal, 1), 5);
    while (startDate < endDate)
    {
        int month = startDate.Month;
        //Set workingDate to the first day of the month.
        var workingDate = new DateTime(startDate.Year, month, 1);
        //Set workingDate to the first occurrence of the DayOfWeek parameter
        workingDate = (int)workingDate.DayOfWeek > (int)dayOfWeek
            ? workingDate.AddDays(7 - (int)workingDate.DayOfWeek + (int)dayOfWeek)
            : workingDate.AddDays((int)dayOfWeek - (int)workingDate.DayOfWeek);

        //Advance the date by the number of days required to satisfy the ordinal parameter
        workingDate = workingDate.AddDays((ordinal - 1) * 7);
        //If the date has crossed the month boundary, step back a week.
        //So the last occurrence of the target day is returned
        workingDate = workingDate.Month != month ? workingDate.AddDays(-7) : workingDate;
        foundDates.Add(workingDate);
        startDate = startDate.AddMonths(1);
    }
    return foundDates;
}

DateTime 的两个列表包含完全相同的值,一直到 HHMMSS。那么为什么断言会失败呢? Assert.AreEqual() 失败,Assert.AreSame() 也是如此!是的,它们不是完全相同的对象,但它们的值是相同的,那么为什么要这么挑剔呢?

更新

我试过 Jon Skeet 的想法 here 像这样:

. . .
var firstNotSecond = mockedMonthsAndTruncatedYears.Except(monthsAndTruncatedYears).ToList();
var secondNotFirst = monthsAndTruncatedYears.Except(mockedMonthsAndTruncatedYears).ToList();
Assert.IsTrue((null == firstNotSecond) && (null == secondNotFirst));

...但是得到,“'System.Collections.Generic.List' 不包含 'Except' 的定义并且没有扩展方法 'Except' 可以找到接受类型 'System.Collections.Generic.List' 的第一个参数(您是否缺少 using 指令或程序集引用?)"

列表是引用类型,因此当您比较两个列表时,您比较的是引用,而不是值。

因此,为了比较列表项目,您应该检查两个列表中的每个项目。

看这里:Compare two List<T> objects for equality, ignoring order

或此处:Quickest way to compare two List<>

这是需要的:

        [TestMethod]
        public void TestGetDatesForNthDOWOfMonth()
        {
            List<DateTime> firstFridaysInFirstQuarterOf2017 = new List<DateTime>
    ();
            // These were determined by looking at a calendar
            firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 1, 6));
            firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 2, 3));
            firstFridaysInFirstQuarterOf2017.Add(new DateTime(2017, 3, 3));
            DayOfWeek dow = DayOfWeek.Friday;
            DateTime startDate = new DateTime(2017, 1, 1);
            DateTime endDate = new DateTime(2017, 3, 31);
            List<DateTime> testFirstFridaysInFirstQuarterOf2017 = 
    RoboReporterConstsAndUtils.GetDatesForNthDOWOfMonth(startDate, endDate, dow, 1);
            var firstNotSecond = 
 firstFridaysInFirstQuarterOf2017.Except(testFirstFridaysInFirstQuarterOf2017).ToList();
            var secondNotFirst = 
    testFirstFridaysInFirstQuarterOf2017.Except(firstFridaysInFirstQuarterOf2017).To
    List();
            Assert.IsTrue((firstNotSecond.Count == 0) && (secondNotFirst.Count 
    == 0));
        }

有趣的是,这些项目没有被视为 same/equal,除非使用 except。