【发布时间】:2018-05-24 13:48:08
【问题描述】:
这个问题的上下文是我正在写的光线追踪器。
我有一个 Surface 类型,理想情况下我希望它是 NoSurface 和 Lambertian 继承的抽象基类。
但是,当我有这个层次结构时,我遇到了以下问题:
let closestIntersection : bool*LineParameter*Surface =
match allIntersectionsWithRealSolutions with
| [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)))
| x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions
这会引发编译器错误,因为它将返回类型绑定到的类型是 NoSurface,即使将类型指定为 Surface。
这解决了问题:
let closestIntersection : bool*LineParameter*Surface =
match allIntersectionsWithRealSolutions with
| [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)) :> Surface)
| x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions
closestIntersection
但是根据 BenchmarkDotNet,与将 Surface 定义为(非抽象)类并简单地返回它的解决方案相比,演员 :> 花费了我 25 毫秒!
我能否以某种方式避免显式转换并获得所需的 Surface 存在和抽象类层次结构?
【问题讨论】:
-
试过
upcast? -
你能提供一个代码示例吗?我对 F# 有点陌生
-
@FuleSnabel 我试过
| [] -> (false,0.0f, (upcast NoSurface(0UL,NotHitable(),Material(Vector3.Zero)) : Surface)),是的,你是对的!它快了很多!也大约 25 毫秒。谢谢!为什么会出现这种性能差异? -
在本地尝试了一下,但我无法重现您看到的性能损失。这可能是因为我没有正确的类型定义。对于此类问题,我建议使用 dotPeek 之类的工具来查看您的代码被编译成什么。有时需要进入 IL 才能看到。
-
嗯,我在一个非常递归的上下文中运行这个。也许在这种情况下进行投射会影响性能?如果你能解释为什么 upcast 比 :> 我会给你正确的答案。
标签: f#