我有一些问题,通过以下代码理解一般约束.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)是否有更令人满意的解决方案呢?
正如John在评论中提到的那样,F#并不(通常)隐式地将类强制转换为基类.因此,如果您创建一个新实例BoxView并在View预期的某个位置使用它,则需要添加一个显式的upcast:
以下内容应与您的原始定义一起使用:
let x = { children = [(new BoxView( Color = Color.Green ) :> View, 0, 3, 0, 1)] }
在一些地方不需要向上播放(最重要的是,当您使用BoxView作为方法的参数时View).我认为F#应该更聪明一些,并且在这种情况下自动插入向上播放...