取消装箱需要元组,但不适用于类型

时间:2013-10-31 16:03:23

标签: f# boxing unboxing

有人可以解释以下内容,似乎有些不一致。

这行代码无效:

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和"一个"被分配到'值'这是一个对象。

为什么我不需要为某个类型的成员取消装箱,但我需要为元组中的某个项目取消?

1 个答案:

答案 0 :(得分:3)

正如评论中所提到的,这有点不一致,但在这种情况下它实际上是有道理的。

重点是编译器永远不会在表达式的子表达式中的任何位置插入装箱。它只会立即执行此操作 - 调用方法或函数(需要obj)或将值分配给记录字段时。但是,当在一些较大的表达式中需要时,它永远不会(*)插入拳击。

因此,在您的示例中,当编译器看到("Hi", 1)("Ho", "One")时,它只会创建两个类型为string * intstring * string的元组 - 然后它会失败,因为这样做不匹配。

当编译器看到{name="Hi"; value=1}时,它会发现您正在创建thing,因此它会自动将值参数设置为obj(然后您最终得到一个有效列表事情)。


(*)唯一的例外是当你创建一个数组或值列表时,但这是编译器中的一个特殊的特殊情况(它恰好非常有用,但对你没有帮助,因为你' d需要不仅在列表中添加装箱,而是在列表内的元组内添加装箱。这是有效的:

let (arr:obj list) = [ 1; "hi" ]