我无法全神贯注地思考为什么在 F# 派生类或接口实现中,当匹配的实例是对象时匹配有效,但当它是某种具体类型时则无效?这背后的概念或其他原因是什么?
例如,如果我们有这样的类层次结构
public class BaseClass
{
}
public class DerivedClass : BaseClass, ISomeInterface
{
public void SomeMethod() => Console.WriteLine("SomeMethod");
}
public interface ISomeInterface
{
void SomeMethod();
}
那么这段 F# 代码将无法编译
member this.Execute(arg: BaseClass) =
match arg with
| :? ISomeInterface as derived -> derived.SomeMethod()
| _ -> printfn "Not a derived class"
但是这个会!
member this.Execute(arg: BaseClass) =
match arg :> obj with
| :? ISomeInterface as derived -> derived.SomeMethod()
| _ -> printfn "Not a derived class"
此编译器行为有任何逻辑解释吗?
这是因为spec这么说的。
F# 语言规范是一份正式描述,旨在与 2015-2016 年时间范围内的 F# 编译器开发保持同步。此后的调整将通过 RFC 进行处理。
7.9 动态类型测试模式
...如果无法静态确定 type 是模式输入类型的子类型,则会发生错误。
这不仅影响动态类型测试模式,还影响
expr :? ty
形式的动态类型测试表达式。考虑:
type ISomeInterface = abstract SomeMethod : unit -> unit
type BaseClass() = class end
type DerivedClass() =
inherit BaseClass()
interface ISomeInterface with member __.SomeMethod() = ()
BaseClass() :? ISomeInterface // doesn't compile
BaseClass() :> obj :? ISomeInterface // evaluates to false
DerivedClass() :> obj :? ISomeInterface // evaluates to true