MiP*_*MiP 1 .net c# clr f# functional-programming
来自Array Covariance文章:
元素类型是引用类型的数组是协变的.[...]它被添加到CLR中,因为Java需要它,而CLR设计者希望能够支持类似Java的语言.
CLR支持数组协方差,但是如何在F#中使用这个方便的功能?
type Foo () = class end
type Bar () = inherit Foo ()
// must have type Foo []
let foo : Foo [] = Array.create 1 (Bar ())
// ^^^^^^ must not cast to Foo
// must throw ArrayTypeMismatchException
foo.[0] <- Foo ()
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我想在场景后面foo存储一个Bar数组,就像在CLR中实现一样.
在C#允许类型之间隐式转换的许多地方,F#需要显式转换.
F#编译器甚至不允许直接强制转换Bar[]为Foo[](类型'Bar []'没有任何正确的子类型,也不能用作类型测试或运行时强制的源.),你需要先强制转换object.
let foo = Array.create 1 (Bar ()) :> obj :?> Foo[]
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我不会将数组协方差称为一个方便的特性,它会导致比它解决的问题更多的问题.
只是为了记录,也许最值得注意的情况是数组协方差是有用的,当你有一个函数需要Foo[]并且你想用Bar[]参数调用它.这是F#泛型所涵盖的内容,因为您可以使用以下#Foo[]语法编写适用于从给定类型继承的任何类型的函数:
type Foo () = class end
type Bar () = inherit Foo ()
let doFooThings (foos:Foo[]) = ()
let doFooThingsBetteer (foos:#Foo[]) = ()
let bars = [| Bar() |]
doFooThings bars // error: The type 'Foo' does not match the type 'Bar'
doFooThingsBetteer bars // no error!
Run Code Online (Sandbox Code Playgroud)