如何在F#中动态取消装箱值?

时间:2015-05-13 09:44:42

标签: f#

我正在尝试在下面的第四行中实现自动/动态演员:

publicTestData generate(SourceOfRandomness random, GenerationStatus status) {...}

以下将在上面的最后一行中工作但是要求我知道并明确标记我正在使用的原始/值类型(我正在努力避免):

let a = 1 // type: int
let b = box a // type: obj
b.GetType() // System.Int32, so it is perfectly aware what it is!
let c = unbox b  // fails....

2 个答案:

答案 0 :(得分:2)

虽然b在运行时知道 是什么,但编译器却没有,因为它是obj

如果知道,在编译时它是什么,你可以像这样取消它:

let a = 1 
let b = box a 
b.GetType()
let c = unbox<int> b

c现在是int

答案 1 :(得分:1)

unbox只有在编译时可以显式或隐式确定类型时才会执行任何操作。在这里,它会隐式(并且错误地)尝试将object转换为string,因为它是在后续行中使用的方式。

let a = 1 
let b = box a 
b.GetType()
let c = unbox b
printf "%s" c

这当然会产生运行时错误,因为是一个字符串。

没有办法让unbox转换为“它实际上是什么”,因为在编译时没有明确的方法来确定它。如果你能提供更多细节,可能还有另一种方法可以做你想做的事。

如果您想要,比如从盒装对象创建一个通用的未装箱列表,您可以这样做:

let addToList (l: 'a list) (o: obj) = // type annotations optional
  let o' = unbox o  // unboxes to generic type 'a
  o'::l

let l = [1;2;3]
let b = box 4
let l' = addToList l b // l' is list<int>, not list<obj>

let l2 = [1.;2.;3.]
let b2 = box 4.
let l2' = addToList l2 b2 // l2' is list<float>

// but as above you still have to be careful
let lcrash = addToList l b2 // crash