有一个类型提供程序,它有三个属性'a','b'和'c',分别是'string','string option'和'int option'。
如果我在这些属性中有“”,“无”和“1”的实例,则会失败:
(row1.a, row1.b, row1.c) |> should equal ("", None, Some 1)
但所有这些都很好:
row1.a |> should equal ""
row1.b |> should equal None
row1.c |> should equal (Some 1)
("", None, Some 1) |> should equal ("", None, Some 1)
这怎么可能?什么可以使b中的None与其他None不同?编译后,None只是一个null,在.Net中可以有两个空值不同吗?
与大多数F#类型一样,元组具有结构上的相同性,因此它应该可以工作。 我得到一个带有Message:
的NUnit.Framework.AssertionExceptionExpected: <(, , Some(1))>
But was: <(, , Some(1))>
NUnit只是调用.Equals,这就是问题所在。
这也失败了:
(row1.a, row1.b, row1.c).Equals(("", None, Some 1)) |> should equal true
row1
的运行时类型为System.Tuple<string,Microsoft.FSharp.Core.FSharpOption<string>,Microsoft.FSharp.Core.FSharpOption<int>>
,所以即使这应该在理论上有效:
row1 |> should equal ("", None, Some 1)
事实上,当元组中没有None
时就会这样做。
除了类型提供程序之外,我无法使用其他任何内容重现此行为。
答案 0 :(得分:5)
我们已经被这几次咬过了,所以我们在此创建a specific note:
FsUnit使用type test来实现其DSL。类型推断在此DSL上不起作用,因此请确保两个比较值属于同一类型。
例如,对于某些通用值,例如True
,False
等,您需要指定其类型(formula<fol>.True
,formula<fol>.False
等),否则这些值将被比较为obj
类型。
如果你看一下how FsUnit is implemented,,它实际上并不是类型安全的。我相信Jack P.'s pull request是使FsUnit更加类型安全的一步。这似乎是一个改善FsUnit的领域。