有人可以解释以下内容,似乎有些不一致。
这行代码无效:
let l = [("Hi", 1); ("Ho", "One")]
因为元组是不同的字符串* int vs string * string OK。
这行代码也无效:
let (m: (string*obj) list) = [("Hi", 1); ("Ho", "One")]
我明确告诉它它是一个字符串* obj元组的列表,但它并不是自动的 施放1和" One"对象好吧也是。
这行代码有效:
let (n: (string*obj) list) = [("Hi", unbox(1)); ("Ho", unbox("One"))]
在这种情况下,我明确地取消了1和" One"它有效。
在这里,我觉得事情有点不一致。 请采取以下措施:
type thing =
{
name: string
value: obj
}
let (p: thing list) = [{name="Hi"; value=1}; {name="Ho"; value="One"}]
该代码有效。值1和"一个"被分配到'值'这是一个对象。
为什么我不需要为某个类型的成员取消装箱,但我需要为元组中的某个项目取消?
答案 0 :(得分:3)
正如评论中所提到的,这有点不一致,但在这种情况下它实际上是有道理的。
重点是编译器永远不会在表达式的子表达式中的任何位置插入装箱。它只会立即执行此操作 - 调用方法或函数(需要obj
)或将值分配给记录字段时。但是,当在一些较大的表达式中需要时,它永远不会(*)插入拳击。
因此,在您的示例中,当编译器看到("Hi", 1)
和("Ho", "One")
时,它只会创建两个类型为string * int
和string * string
的元组 - 然后它会失败,因为这样做不匹配。
当编译器看到{name="Hi"; value=1}
时,它会发现您正在创建thing
,因此它会自动将值参数设置为obj
(然后您最终得到一个有效列表事情)。
(*)唯一的例外是当你创建一个数组或值列表时,但这是编译器中的一个特殊的特殊情况(它恰好非常有用,但对你没有帮助,因为你' d需要不仅在列表中添加装箱,而是在列表内的元组内添加装箱。这是有效的:
let (arr:obj list) = [ 1; "hi" ]