如何动态取消F#中的值的装箱?
我正在尝试实现下面第四行中的自动/动态转换:如何动态取消F#中的值的装箱?,f#,F#,我正在尝试实现下面第四行中的自动/动态转换: 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.... 以下内容适用于上面的最后一行,但需要我提前知道并明确标记我正在使用的原语/值类型(我正试图避免): 虽然b在运行时知道它是什么,但编译器不知道,因为它是obj
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....
以下内容适用于上面的最后一行,但需要我提前知道并明确标记我正在使用的原语/值类型(我正试图避免):
虽然
b
在运行时知道它是什么,但编译器不知道,因为它是obj
如果在编译时知道它是什么,可以按如下方式取消装箱:
let a = 1
let b = box a
b.GetType()
let c = unbox<int> b
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
设a=1
设b=方框a
b、 GetType()
设c=unbox b
c
现在是一个int
unbox
仅在编译时可以显式或隐式确定类型时才执行任何操作。在这里,它会隐式地(错误地)尝试将对象
转换为字符串
,因为这就是它在后续行中的用法
let a = 1
let b = box a
b.GetType()
let c = unbox b
printf "%s" c
这当然会导致运行时错误,因为它不是字符串
没有办法让unbox
转换为“它实际上是什么”,因为在编译时没有确定的方法来确定这一点。如果你能提供更多的细节,也许还有另一种方法来做你想做的事情
如果您想从已装箱的对象创建一个通用的未装箱列表,可以执行以下操作:
let a = 1
let b = box a
b.GetType()
let c = unbox<int> b
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
let addToList(l:'a list)(o:obj)=//类型注释可选
设o'=unbox o//unbox为泛型类型“a”
o’::l
设l=[1;2;3]
设b=方框4
设l'=addToList l b//l'是列表,而不是列表
设l2=[1.;2.;3.]
设b2=方框4。
设l2'=addToList l2 b2//l2'为列表
//但如上所述,你仍然必须小心
让lcrash=addToList l b2//崩溃
谢谢。我试图避免在编译时直接使用,因为我设想了一种可能是其他值类型的场景。是否有一种方法可以在运行时从“b”中动态提取类型,并在强制转换/取消打包中使用该类型?@Sam-如果您不知道预期的类型是什么,则无法强制转换它。如果您不需要知道确切的类型,那么您不需要做任何事情,因为正如您所看到的,该类型是在运行时维护的。您在这里实际要做什么?虽然这是可能的,但它往往会变得非常笨拙,并且会失去F#type系统的安全性。编译器知道的和运行时知道的是有区别的。运行库知道obj
是什么类型,只需像上面那样调用GetType
来询问它。但是,编译器只知道它是一个obj
,它可以是int
,字符串
等等。在您的示例中,有人可能认为F#编译器可以通过查看表达式树推断b
实际上是一个int
,但这只适用于普通情况,那么为什么要使用box呢?