不考虑类型参数的子类测试

Subclass test without regard to type argument

如果你运行:

type Car<'T> () = class end
type Mercedes () =
    inherit Car<int> ()
let merc = Mercedes ()

然后 运行 以下每一行,您将获得指示的结果:

merc :? Mercedes        // true
box merc :? Mercedes    // true
merc :? Car<int>        // error FS0193: types not compatible
box merc :? Car<int>    // true
merc :? Car<_>          // error FS0193: types not compatible
box merc :? Car<_>      // false
  1. 查看前四种情况。为什么你需要框 merc 用于针对 Car<int> 的测试,而不用于针对 Mercedes 的测试?
  2. 在最后两种情况下,我试图找到 return true 因为 mercCar,而不考虑类型参数.有这种东西吗?

要回答你的第二个问题,没有 built-in 运算符来测试一个值是否继承自 class 而不管类型参数。您可以通过获取 Mercedes 的基类型并将其泛型类型定义与 Car<_>:

的泛型类型定义进行比较来使用反射来检查这一点
merc.GetType().BaseType.GetGenericTypeDefinition() = typedefof<Car<_>>

在实践中,引入 non-generic 基础 class 可能更容易:

type Car() = class end
type Car<'T> () = 
    inherit Car()
type Mercedes () =
    inherit Car<int> ()

let merc = Mercedes ()
box merc :? Car

为了回答您的第一个问题,我认为编译器会提示您该操作没有用,因为它总是会成功 - 因此使用 :?.[=19= 进行检查没有意义]

如果您有一个静态类型为 Car<int> 的值,并且您想检查它是否为 Mercedes,这是不允许的,因为这是一个有趣的问题:

Car<int>() :? Mercedes

但是不允许检查 Car<obj>() :? Mercedes,因为这在静态上已知是错误的。

回答你的第一个问题:

Why do you need to box merc for the test against Car<int>, but not for the test against Mercedes?

来自docs类型测试运算符 :?

Returns true if the value matches the specified type (including if it is a subtype); otherwise, returns false

第 4 行 box merc :? Car<int> 成功,因为 box merc 将层次结构中的类型上升到最高类型 object

第 3 行 merc :? Car<int> 应该有 return false 因为 Mercedes > Car<int>。相反,它不是编译,这是一种没有记录的行为,但对我来说也不足为奇,因为我们总是知道它不可能是真的。请注意,它可能只是一个警告,就像在 C# 中我们编写 if (true) ....

但令人惊讶的是,为什么此行为不适用于第 1 行 merc :? Mercedes。由于“显而易见”的相同原因,它应该无法编译。相反,它只是一个警告 FS0067: This type test or cast of a base class into a derived class will always succeed

结论: 类型测试运算符 实际上是作为 向下转型测试运算符设计的。 在其他情况下使用它,比如检查向上转换可能会产生误导(在编译时),但在运行时仍然安全。