记录类型的通用约束

时间:2015-10-12 11:17:11

标签: generics f#

我有一些问题,通过以下代码理解一般约束。 View是Xamarin框架中的基类(但这并不重要)

type GridCoordinates = (View * int * int * int * int)
type GridRecord = { children: GridCoordinates list}

根据这段代码我在这里得到一个编译错误

let x = { children = [(new BoxView( Color = Color.Green ), 0, 3, 0, 1)] }
                       ^^^^^^^^^^^
                       Expression expected to have type View

现在BoxView的类型为View - 嗯。所以我想我会在其中添加一些通用约束

type GridCoordinates<'T when 'T :> View> = ('T * int * int * int * int)
type GridRecord = { children: GridCoordinates<View> list}

但是这仍然给了我同样的错误。所以我也向GridRecord添加了一个constrait

type GridCoordinates<'T when 'T :> View> = ('T * int * int * int * int)
type GridRecord<'T when 'T :> View> = { children: GridCoordinates<'T> list}

现在它编译。我甚至可以从GridCoordinates中删除约束,以便

type GridCoordinates<'T> = ('T * int * int * int * int)
type GridRecord<'T when 'T :> View> = { children: GridCoordinates<'T> list}

现在所有这些都是非常繁重的语法加上应该在GridCoordinates上的约束会侵入GridRecord的定义,这不是很好(imo)。

有人可以向我解释

a)为什么这有效,因为它有效 b)对此有更令人满意的解决方案吗?

1 个答案:

答案 0 :(得分:6)

正如John在评论中提到的,F#并不(通常)隐式地将类强制转换为基类。因此,如果您创建BoxView的新实例并在需要View的某个地方使用它,则需要添加一个明确的 upcast

以下内容适用于您的原始定义:

let x = { children = [(new BoxView( Color = Color.Green ) :> View, 0, 3, 0, 1)] }

在一些地方不需要向上播放(最重要的是,当您使用BoxView作为采用View的方法的参数时。我认为F#应该更智能一点,并且在这种情况下自动插入向上播放...

相关问题