代码之家  ›  专栏  ›  技术社区  ›  Marc Gravell

开关/模式匹配思想

  •  142
  • Marc Gravell  · 技术社区  · 17 年前

    我最近一直在关注F#,虽然我不太可能在短期内跳过篱笆,但它肯定突出了一些C#(或图书馆支持)可以让生活更轻松的领域。

    特别是,我在考虑F#的模式匹配功能,它允许非常丰富的语法-比当前的开关/条件C#等价物更具表现力。我不会试图给出一个直接的例子(我的F#无法胜任),但简而言之,它允许:

    • 按类型匹配(对有区别的联合进行全覆盖检查)[注意,这也会推断绑定变量的类型,给予成员访问权等]
    • 上述情况的组合(可能还有一些我不知道的其他情况)

    虽然C#最终能够借用[ahem]这种丰富性会很不错,但在此期间,我一直在研究在运行时可以做些什么——例如,将一些对象组合在一起以允许:

    var getRentPrice = new Switch<Vehicle, int>()
            .Case<Motorcycle>(bike => 100 + bike.Cylinders * 10) // "bike" here is typed as Motorcycle
            .Case<Bicycle>(30) // returns a constant
            .Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
            .Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
            .ElseThrow(); // or could use a Default(...) terminator
    

    其中getRentPrice是一个函数<车辆,int>。

    [注意-这里的Switch/Case可能是错误的术语…但它表明了这个想法]

    大量 并允许简单扩展(直接或通过扩展方法)到更具体的匹配,例如与VB Select…Case“x到y”用法类似的InRange(…)匹配。

    另外请注意,我一直在使用上述3种变体:

    • a Func<t来源,TValue>评估版本-可与复合三元条件语句进行比较
    • 表达式<Func<t来源,TValue>&燃气轮机;版本-作为第一个,但可由任意LINQ提供程序使用

    此外,使用基于条件的表达式调用,而不是使用基于条件的表达式重新写入到一个复合表达式树中。我最近没有检查,但在一些早期的实体框架构建中,我似乎记得这是必要的,因为它不太喜欢调用表达式。它还允许更有效地使用LINQ to对象,因为它避免了重复的委托调用-测试显示了类似于上述(使用表达式形式)的匹配,与等效的C#复合条件语句相比,它以相同的速度[事实上稍微快一点]执行。为完整起见,函数<&燃气轮机;基于C#conditional语句的版本花费的时间是C#conditional语句的4倍,但仍然非常快,在大多数用例中不太可能成为主要瓶颈。

    11 回复  |  直到 4 年前