写点什么

.NET 4 中的模式匹配

  • 2009-05-30
  • 本文字数:3531 字

    阅读完需:约 12 分钟

case 语句可以看作是 if/else 语法的特别版。他们的功能和作用是一样的,但有时 case 语句会令代码看起来更加清爽。考虑下面的 C#和 VB 示例。

复制代码
<span>double </span>CaclRateByDate(<span>DayOfWeek </span>day)
{
<span>if </span>(day == <span>DayOfWeek</span>.Monday)
{
<span>return </span>.42;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Tuesday)
{
<span>return </span>.67;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Wednesday)
{
<span>return </span>.56;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Thursday)
{
<span>return </span>.34;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Friday)
{
<span>return </span>.78;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Saturday)
{
<span>return </span>.92;
}
<span>else if </span>(day == <span>DayOfWeek</span>.Sunday)
{
<span>return </span>.18;
}
<span>throw new </span><span>ArgumentOutOfRangeException</span>(<span>"Unexpected enum value"</span>);
}
复制代码
<span>Function </span>CaclRateByDate(<span>ByVal </span>day <span>As </span>DayOfWeek) <span>As Double
If </span>day = Monday <span>Then
Return </span>0.42
<span>ElseIf </span>day = Tuesday <span>Then
Return </span>0.67
<span>ElseIf </span>day = Wednesday <span>Then
Return </span>0.56
<span>ElseIf </span>day = Thursday <span>Then
Return </span>0.34
<span>ElseIf </span>day = Friday <span>Then
Return </span>0.78
<span>ElseIf </span>day = Saturday <span>Then
Return </span>0.92
<span>ElseIf </span>day = Sunday <span>Then
Return </span>0.18
<span>Else
Throw New </span>ArgumentOutOfRangeException(<span>"Unexpected enum value"</span>)
<span>End If
End Function</span>

开发者需要一遍又一遍地编写“ElseIf day =”或“else if (day ==”这种语句,但却并没有增加任何信息。这种语句简直就是一种折磨,不停地分散开发者的注意力,我指的是 DayOfWeek 和返回值。

在 VB 和 C#中,我们可以通过 case 语句进行简化。

复制代码
<span>double </span>CaclRateByDate2(<span>DayOfWeek </span>day)
{
<span>switch </span>(day)
{
<span>case </span><span>DayOfWeek</span>.Monday:
<span>return </span>.42;
<span>case </span><span>DayOfWeek</span>.Tuesday:
<span>return </span>.67;
<span>case </span><span>DayOfWeek</span>.Wednesday:
<span>return </span>.56;
<span>case </span><span>DayOfWeek</span>.Thursday:
<span>return </span>.34;
<span>case </span><span>DayOfWeek</span>.Friday:
<span>return </span>.78;
<span>case </span><span>DayOfWeek</span>.Saturday:
<span>return </span>.92;
<span>case </span><span>DayOfWeek</span>.Sunday:
<span>return </span>.18;
<span>default</span>:
<span>throw new </span><span>ArgumentOutOfRangeException</span>(<span>"Unexpected enum value"</span>);
}
}
复制代码
<span>Function </span>CalcRateByDate2(<span>ByVal </span>day <span>As </span>DayOfWeek) <span>As Double
Select Case </span>day
<span>Case </span>Monday
<span>Return </span>0.42
<span>Case </span>Tuesday
<span>Return </span>0.67
<span>Case </span>Wednesday
<span>Return </span>0.56
<span>Case </span>Thursday
<span>Return </span>0.34
<span>Case </span>Friday
<span>Return </span>0.78
<span>Case </span>Saturday
<span>Return </span>0.92
<span>Case </span>Sunday
<span>Return </span>0.18
<span>Case Else
Throw New </span>ArgumentOutOfRangeException(<span>"Unexpected enum value"</span>)
<span>End Select
End Function</span>

即便如此还是有不少的重复代码。为什么总是不断地说需要一个返回值呢?像下面这样写岂不更好?

复制代码
<span>double </span>CaclRateByDate2(<span>DayOfWeek </span>day)
{
<span>return switch </span>(day)
{
<span>DayOfWeek</span>.Monday: .42;
<span>DayOfWeek</span>.Tuesday: .67;
<span>DayOfWeek</span>.Wednesday: .56;
<span>DayOfWeek</span>.Thursday: .34;
<span>DayOfWeek</span>.Friday: .78;
<span>DayOfWeek</span>.Saturday: .92;
<span>DayOfWeek</span>.Sunday: .18;
<span>default</span>:
<span>throw new </span><span>ArgumentOutOfRangeException</span>(<span>"Unexpected enum value"</span>);
}
}
复制代码
<span>Function </span>CalcRateByDate2(<span>ByVal </span>day <span>As </span>DayOfWeek) <span>As Double
Return Select Case </span>day
Monday: 0.42
Tuesday: 0.67
Wednesday: 0.56
Thursday: 0.34
Friday: 0.78
Saturday: 0.92
Sunday: 0.18
<span>Case Else
Throw New </span>ArgumentOutOfRangeException(<span>"Unexpected enum value"</span>)
<span>End Select
End Function</span>

在消除了那些不必要的重复后,你会发现 C#和 VB 代码看起来是如此的接近。剩下的代码就是寻找的模式以及与模式所匹配的结果了。这就是众所周知的模式匹配

遗憾的是,在C# 4 和VB 10 中并没有提供该特性,但却有一门新语言提供了对模式匹配的支持。看看下面这个由 Mathew Podwysocki 编写的 F#示例(需要说明的是,在下面这些示例中都创建了相应的函数)。

复制代码
<span>let</span> calcRateByDay2 (day:System.DayOfWeek) =
<span>match</span> day <span>with </span>
| System.DayOfWeek.Monday -> 0.42
| System.DayOfWeek.Tuesday -> 0.67
| System.DayOfWeek.Wednesday -> 0.56
| System.DayOfWeek.Thursday -> 0.34
| System.DayOfWeek.Friday -> 0.78
| System.DayOfWeek.Saturday -> 0.92
| System.DayOfWeek.Sunday -> 0.18
| _ -> failwith "Unexpected enum value"

接下来 Mathew 又介绍了同时检查多个参数的方式。下面这个示例将下划线当作通配符。

复制代码
<span>let</span> allowUrl url port =
<span>match</span> (url, port) <span>with</span>
| "http://www.microsoft.com/", 80 -> true
| "http://example.com/", 8888 -> true
| _, 80 -> true
| _ -> false

遗憾的是,F#的语法并不简洁。如果想要操纵某个值,那就不得不通过名称或占位符来指定了。

复制代码
<span>let</span> calcRateByDay3 (day:System.DayOfWeek) =
<span>match</span> day <span>with </span>
| x when x >= System.DayOfWeek.Monday && x <= System.DayOfWeek.Friday -> 0.42
| System.DayOfWeek.Saturday -> 0.92
| System.DayOfWeek.Sunday -> 0.18
| _ -> failwith "Unexpected enum value"
<span>let</span> calcRateByDay3 (day:System.DayOfWeek) =
<span>match</span> day <span>with </span>
| _ when day >= System.DayOfWeek.Monday && day <= System.DayOfWeek.Friday -> 0.42
| System.DayOfWeek.Saturday -> 0.92
| System.DayOfWeek.Sunday -> 0.18
| _ -> failwith "Unexpected enum value"

下面的代码用 VB 的 case 语句实现同样的功能。

复制代码
<span>Function </span>CaclRateByDate3(<span>ByVal </span>day <span>As </span>DayOfWeek) <span>As Double
Select Case </span>day
<span>Case </span>Monday <span>To </span>Friday : <span>Return </span>0.42
<span>Case </span>Saturday : <span>Return </span>0.92
<span>Case </span>Sunday : <span>Return </span>0.18
<span>Case Else
Throw New </span>ArgumentOutOfRangeException(<span>"Unexpected enum value"</span>)
<span>End Select
End Function</span>

如你所见,.NET 平台上的每种语言都有自己的一些语法优势,可以将他们应用到其他语言上而无需改变语言的核心。

查看英文原文: Pattern Matching in .NET 4

2009-05-30 22:311965
用户头像

发布了 88 篇内容, 共 273.8 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

Fegin的解析

卢卡多多

OpenFegin 6月月更

如何在物联网低代码平台中使用数据字典功能?

AIRIOT

物联网 低代码平台

为 Serverless Devs 插上 Terraform 的翅膀,解耦代码和基础设施,实现企业级多环境部署(下)

阿里巴巴云原生

阿里云 开源 云原生 Serverless Devs

51万奖池邀你参战!第二届阿里云ECS CloudBuild开发者大赛来袭

阿里云弹性计算

阿里云 分布式缓存 开发者大赛 加密计算 大数据加速

axios(二)

小恺

6月月更

linux之git入门命令

入门小站

Linux

博睿数据出席阿里云可观测技术峰会,数字体验管理驱动可持续发展

博睿数据

可观测性 智能运维 博睿数据 数字体验管理

5分钟快速上线Web应用和API(Vercel)

Liam

前端 前端开发 开发 Postman API

数据科学家是不是特有前途的职业?

袁袁袁袁满

一张图解码 OpenCloudOS 社区开放日

腾源会

华为云如何实现实时音视频全球低时延网络架构【上】

坚果

6月月更

一篇文章学会er图绘制

工程师日月

6月月更

flutter系列之:flutter中的Wrap

程序那些事

flutter 程序那些事 6月月更

在线JSON转CSharp(C#)Class工具

入门小站

工具

使用GetX构建更优雅的Flutter页面结构

岛上码农

flutter ios 前端 安卓开发 6月月更

Java基础:反射机制详解

百思不得小赵

javase 反射机制 6月月更

Android 11适配指南之系统相机拍照、打开相册

yechaoa

android 适配 6月月更 11.0

支持在 Kubernetes 运行,添加多种连接器,SeaTunnel 2.1.2 版本正式发布!

Apache SeaTunnel

Apache 大数据 开源 workflow

JVM调优简要思想及简单案例-为什么需要JVM调优?

zarmnosaj

6月月更

什么是元数据

奔向架构师

数据仓库 元数据 6月月更

在线文本过滤小于指定长度工具

入门小站

工具

物联网开源开发平台 Shifu 开放内测!第一版技术文档发布

亚马逊云科技 (Amazon Web Services)

物联网 Tech 专栏

年中大促 | 集成无忧,超值套餐 6 折起

融云 RongCloud

数字经济加速落地,能为中小企业带来什么?

脑极体

数据库每日一题---第20天:按日期分组销售产品

知心宝贝

数据库 程序员 前端 后端 6月月更

一篇文章带你对Java对象创建过程解密

派大星

JVM

Java Core 「15」J.U.C Executor 框架

Samson

学习笔记 Java core 6月月更

如何低成本快速搭建企业知识库?

小炮

C语言字符串与内存库函数的介绍与模拟实现

未见花闻

6月月更

一文简述:钓鱼攻击知多少

穿过生命散发芬芳

6月月更 钓鱼攻击

leetcode 91. Decode Ways 解码方法(中等)

okokabcd

LeetCode 动态规划 算法与数据结构

.NET 4中的模式匹配_.NET_Jonathan Allen_InfoQ精选文章