C# 为什么这两个集合不相等?

C# 为什么这两个集合不相等?,c#,f#,xunit,C#,F#,Xunit,在使用XUnit编写一些单元之前,我遇到了一些令人惊讶的事情: let id=Guid.Empty 让联系人={ 姓名={ FirstName=“Marcel” 初始值=无 LastName=“Patulacci” } DateOfBith=新的日期时间(1850,12,25) 地址={ Address1=“41 av 8 Mai 1945” 地址2=无 City=“Sarcelles” 状态=无 Zip=“95200” } 电话号码={ 拨号代码=33 LocalNumber=“7660307

在使用XUnit编写一些单元之前,我遇到了一些令人惊讶的事情:

let id=Guid.Empty
让联系人={
姓名={
FirstName=“Marcel”
初始值=无
LastName=“Patulacci”
}
DateOfBith=新的日期时间(1850,12,25)
地址={
Address1=“41 av 8 Mai 1945”
地址2=无
City=“Sarcelles”
状态=无
Zip=“95200”
}
电话号码={
拨号代码=33
LocalNumber=“766030703”
}
Email=“马塞尔。patulacci@outlook.com"
}
[]
让``开户……`()=
让event=event.AccountOpened({
AccountId=id
接触
})
设a=[事件]
设b=seq{yield event}
断言相等(a,b)
System.NullReferenceException
:对象引用未设置为对象的实例

考虑到
Assert
使用的重载是:

public static void Equal(预期为IEnumerable,实际为IEnumerable)
其中指出:

使用默认比较器验证两个序列是否相等

为什么认为它们不同,为什么
断言.Equal
引发
系统.NullReferenceException

[编辑]

System.NullReferenceException
:对象引用未设置为对象的实例。 在
Domain.Events.AccountOpenedEvent.Equals(objectobj,IEqualityComparer comp)
Domain.Events.Event.Equals(objectobj,IEqualityComparer comp)

似乎


键入PersonalName={
名字:字符串;
MiddleInitial:字符串选项;
LastName:string;
}
类型地址={
地址1:字符串;
地址2:字符串选项;
城市:字符串;
状态:字符串选项;
拉链:细绳;
}
类型电话号码={
拨号代码:int;
LocalNumber:string
}
类型联系人={
姓名:个人姓名;
DateOfBith:DateTime
电子邮件:字符串;
地址:地址;
电话号码:电话号码
}
类型AccountOpenedEvent={
帐户ID:Guid
联系人:联系人
}
类型事件=
|AccountOpenedEvent的AccountOpened

事实证明,
event
的其中一个字段是
null
,而不是
event
本身。

问题存在于测试的正上方定义的
id
contact

let id=Guid.Empty
让联系人={
姓名={
FirstName=“Marcel”
初始值=无
LastName=“Patulacci”
}
DateOfBith=新的日期时间(1850,12,25)
地址={
Address1=“41 av 8 Mai 1945”
地址2=无
City=“Sarcelles”
状态=无
Zip=“95200”
}
电话号码={
拨号代码=33
LocalNumber=“766030703”
}
Email=“马塞尔。patulacci@outlook.com"
}
[]
让``开户……`()=
让event=event.AccountOpened({
AccountId=id
接触
})
设a=[事件]
设b=seq{yield event}
断言相等(a,b)
问题是当独立运行测试时,
id
contact
没有初始化,因此即使
事件
不是
null
,contact也是
null
id
Guid
又称为
struct
它仍然有一个值)

由于F#与结构相等一起工作,如果其中一个字段未初始化,则有一个字段
null
足以使
Assert
在其实现的某个点失败

有几种解决方案/变通方法:

  • 直接在单元测试体中定义这些变量
  • 定义从单元测试体中产生这些值的方法
  • 让getId()=Guid.Empty
    让getContact()={
    姓名={
    FirstName=“Marcel”
    初始值=无
    LastName=“Patulacci”
    }
    DateOfBith=新的日期时间(1850,12,25)
    地址={
    Address1=“41 av 8 Mai 1945”
    地址2=无
    City=“Sarcelles”
    状态=无
    Zip=“95200”
    }
    电话号码={
    拨号代码=33
    LocalNumber=“766030703”
    }
    Email=“马塞尔。patulacci@outlook.com"
    }
    []
    让``开户……`()=
    让id=getId()
    let contact=getContact()
    让event=event.AccountOpened({
    AccountId=id
    接触
    })
    设a=[事件]
    设b=seq{yield event}
    断言相等(a,b)
    
    虽然这些变通方法可行,但我感到惊讶的是,当测试运行/未初始化时,单元测试函数正上方声明的变量没有被考虑

    也许值得再问一个问题,为什么会这样。
    这在某种意义上是令人惊讶的,如果一个函数可以被定义并返回与这些变量几乎相同的东西,这意味着let也被正确编译,那么为什么变量不是这样呢?

    你确定
    事件
    不是空值吗?我敢打赌
    Assert.Equal
    是用类似
    actual.Equals(预期)
    的东西实现的,如果
    actual
    为null,则会抛出。不是这样,我在
    Assert.Equal
    中设置了一个断点,在那个阶段,两个参数都是非null的。请添加完整的示例和完整的异常消息。可能空引用异常不是来自您提供的测试?您声称,
    Assert.Equal
    正在引发异常,但它不可能引发异常。这些陈述中只有一个是正确的。@DanWilson“但是它不可能抛出异常”我没有声明。@DanWilson你可以检查我的答案