I am trying to achieve the automatic/dynamic cast in the fourth line below:
我试图在下面的第四行实现自动/动态转换:
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....
The following would would work in the final line above BUT would require me to know and explicitly mark ahead-of-time the primitive/value type that I am working with (which I am trying to avoid):
以下将在上面的最后一行中工作但是要求我知道并明确标记我正在使用的原始/值类型(我试图避免):
let c1:int = unbox b
let c2 = b :?> int
2 个解决方案
#1
While b
knows at run-time what it is, the compiler doesn't, because it's an obj
.
虽然b在运行时知道它是什么,但编译器没有,因为它是一个obj。
If you know, at compile time, what it is, you can unbox it like this:
如果你知道,在编译时,它是什么,你可以像这样取消它:
let a = 1
let b = box a
b.GetType()
let c = unbox<int> b
c
is now an int
.
c现在是一个int。
#2
unbox
only does anything if the type can be explicitly or implicitly determined at compile time. Here it will implicitly (and wrongly) try to convert the object
to a string
, as that's how it is used in the subsequent line.
如果可以在编译时显式或隐式确定类型,则unbox仅执行任何操作。在这里它将隐式(并且错误地)尝试将对象转换为字符串,因为它是在后续行中使用它的方式。
let a = 1
let b = box a
b.GetType()
let c = unbox b
printf "%s" c
This of course gives a runtime error because it is not a string.
这当然会产生运行时错误,因为它不是字符串。
There's no way to have unbox
convert to "what it actually is under the hood", as there's no definite way of determining this at compile time. There may be another way to do what you're trying to do though, if you can provide more details.
没有办法将unbox转换为“它实际上是什么内容”,因为在编译时没有明确的方法来确定它。如果您可以提供更多详细信息,可能还有另一种方法可以执行您尝试执行的操作。
If you're wanting to, say create a generic unboxed list from boxed objects, you can do something like this:
如果你想要,比如从盒装对象创建一个通用的未装箱列表,你可以这样做:
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
#1
While b
knows at run-time what it is, the compiler doesn't, because it's an obj
.
虽然b在运行时知道它是什么,但编译器没有,因为它是一个obj。
If you know, at compile time, what it is, you can unbox it like this:
如果你知道,在编译时,它是什么,你可以像这样取消它:
let a = 1
let b = box a
b.GetType()
let c = unbox<int> b
c
is now an int
.
c现在是一个int。
#2
unbox
only does anything if the type can be explicitly or implicitly determined at compile time. Here it will implicitly (and wrongly) try to convert the object
to a string
, as that's how it is used in the subsequent line.
如果可以在编译时显式或隐式确定类型,则unbox仅执行任何操作。在这里它将隐式(并且错误地)尝试将对象转换为字符串,因为它是在后续行中使用它的方式。
let a = 1
let b = box a
b.GetType()
let c = unbox b
printf "%s" c
This of course gives a runtime error because it is not a string.
这当然会产生运行时错误,因为它不是字符串。
There's no way to have unbox
convert to "what it actually is under the hood", as there's no definite way of determining this at compile time. There may be another way to do what you're trying to do though, if you can provide more details.
没有办法将unbox转换为“它实际上是什么内容”,因为在编译时没有明确的方法来确定它。如果您可以提供更多详细信息,可能还有另一种方法可以执行您尝试执行的操作。
If you're wanting to, say create a generic unboxed list from boxed objects, you can do something like this:
如果你想要,比如从盒装对象创建一个通用的未装箱列表,你可以这样做:
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