Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何动态取消F#中的值的装箱?_F# - Fatal编程技术网

如何动态取消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呢?