不考虑类型参数的子类测试
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
- 查看前四种情况。为什么你需要框
merc
用于针对 Car<int>
的测试,而不用于针对 Mercedes
的测试?
- 在最后两种情况下,我试图找到 return
true
因为 merc
是 Car
,而不考虑类型参数.有这种东西吗?
要回答你的第二个问题,没有 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
结论: 类型测试运算符 实际上是作为 向下转型测试运算符设计的。 在其他情况下使用它,比如检查向上转换可能会产生误导(在编译时),但在运行时仍然安全。
如果你运行:
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
- 查看前四种情况。为什么你需要框
merc
用于针对Car<int>
的测试,而不用于针对Mercedes
的测试? - 在最后两种情况下,我试图找到 return
true
因为merc
是Car
,而不考虑类型参数.有这种东西吗?
要回答你的第二个问题,没有 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 againstCar<int>
, but not for the test againstMercedes
?
来自docs,类型测试运算符 :?
Returns
true
if the value matches the specified type (including if it is a subtype); otherwise, returnsfalse
第 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
结论: 类型测试运算符 实际上是作为 向下转型测试运算符设计的。 在其他情况下使用它,比如检查向上转换可能会产生误导(在编译时),但在运行时仍然安全。