【问题标题】:F# Testing for Base Types With Pattern Matching and Boxing of Tuples使用元组的模式匹配和装箱对基类型进行 F# 测试
【发布时间】:2023-01-08 00:38:55
【问题描述】:

我试图理解基本类型的装箱和测试的概念,尤其是元组。

我有两个来自外部 C# 库的对象,它们具有不同的具体类型但共享一个公共基类型:

let o1 = ConcreteType1() // has base type BaseType
let o2 = ConcreteType2() // also has base type BaseType

如果o1o2都派生自BaseType,我必须执行一些特殊的比较逻辑,所以我想测试元组(o1, o2)的元素是否都具有基类型BaseType

基于answers to this question,我想我必须装箱每个元素类型的分别地并对单个元素执行类型测试,以便考虑基本类型:

match box o1, box o2 with
| (:? BaseType), (:? BaseType) -> // special logic with o1, o2
| _ -> // nope, some other behavior

我的理解是,简单地装箱元组本身不会将单个元素向上转换为 obj,因此对它们的基本类型的测试将不起作用:

match box (o1, o2) with
| :? (BaseType * BaseType) -> // never hit, because elements are not upcast to obj
| _ -> // ...

这是对观察到的行为的正确解释,还是涉及其他机制?

【问题讨论】:

    标签: f# boxing type-testing


    【解决方案1】:

    装箱元组确实不会装箱元组的项目。但是,即使您也手动装箱这些项目,它仍然不匹配。所以下面的代码打印"Unknown"

    match box (box o1, box o2) with
        | :? (BaseType * BaseType) -> printfn "BaseType"
        | _ -> printfn "Unknown"   // hit
    

    这是因为ConcreteType1 * ConcreteType2不是BaseType * BaseTypeobj * obj 的子类型。请注意,以下代码甚至无法编译:

    let testBad (tuple : BaseType * BaseType) =
        tuple :?> (ConcreteType1 * ConcreteType2)   // compiler error: can't cast
    

    这意味着以下代码将打印"ConcreteType"

    match box (o1, o2) with
        | :? (BaseType * BaseType) -> printfn "BaseType"
        | :? (ConcreteType1 * ConcreteType2) -> printfn "ConcreteType"   // hit
        | _ -> printfn "Unknown"
    

    这正是多态类型与 OO 子类型交互的方式。作为另一个示例,List<ConcreteType1> 不是 List<BaseType> 的子类型,因此再多的装箱和转换也无法使它们匹配。

    令人困惑的是,F# 确实有一种特殊情况,它会自动转换 ConcreteType1 * ConcreteType2 参数以匹配 BaseType * BaseType 参数:

    let testGood (tuple : BaseType * BaseType) =
        printfn "good"
    
    testGood (o1, o2)   // this works and prints "good"
    

    我认为这是因为元组参数在其他语言中很常见,所以 F# 试图保持兼容性,但我不确定。

    【讨论】:

      猜你喜欢
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多