这个问题的背景是我正在写的光线跟踪器。
我有一个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,演员:>
花了我25ms,相比之下,将Surface定义为(非抽象)类而只是简单地返回它的解决方案!
我可以以某种方式避免显式转换并具有所需的Surface is和抽象类层次结构吗?
答案 0 :(得分:3)
您可以尝试使用有区别的联盟解决同样的问题,这将是更具功能性的联盟。因为你正在使用F#?虽然我有点确定这种方法可能会慢一些。但是,如果您在最高性能之后,托管语言不是最好的选择。 在https://fsharpforfunandprofit.com/posts/discriminated-unions/
找到一个好的工会解释这样的事情。
type Intersectable =
| Sphere of center:Point3 * radius:float
| Triangle of v0:Point3 * v1:Point3 * v2:Point3
| MeshTriangle of faceIndex:int * mesh:Mesh
| Instance of Intersectable * Matrix.Matrix4x4
| Plane of normal:Vec3 * pointOnPlane: Point3
共享/通用功能可以通过使用您的功能所依据的通用数据部分来解决,您可能拥有:
type Shape = {
geometry: Intersectable
material: Material }