写点什么

.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:311943
用户头像

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

关注

评论

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

性能调试 -- Chrome Performance

空城机

chrome Performance 7月月更

动画曲线天天用,你能自己整一个吗?看完这篇你就会了!

岛上码农

flutter ios 前端 安卓开发 签约计划第三季

这次龙蜥展区玩的新花样,看看是谁的 DNA 动了?

OpenAnolis小助手

龙蜥社区 北京 开放原子全球开源峰会 7 月 27 日-29 日 分论坛

Bootstrap快捷开发【前端Bootstrap框架】

恒山其若陋兮

7月月更

栈与Stack类

未见花闻

7月月更

互联网协议之 IPFS

devpoint

区块链 IPFS Filecoin 7月月更

聊聊sql优化的15个小技巧

苏三说技术

sql SQL优化

Docker 搭建 Redis Cluster集群

宁在春

redis Docker 集群 7月月更

git merge 不为人知的秘密

蛋先生DX

git merge 最长公共子序列 签约计划第三季 three-way 3-way

vue2升级vue3:vue3创建全局属性和方法

zhoulujun

Vue3 全局变量 全局方法

高效生成接口文档好方法

Xd

数据库 接口测试

ORIGYN基金会正式启动$OGY Staking,引领新一轮生态利好

鳄鱼视界

IPv4地址已经完全耗尽,互联网还能正常运转,NAT是最大功臣!

wljslmz

NAT ipv4 网络技术 7月月更

数据质量:数据治理的核心

奔向架构师

数据治理 7月月更

Baklib:制作优秀的产品说明手册

Baklib

怎样设计产品帮助中心?以下几点不可忽视

Baklib

JS作用域与作用域链

程序员海军

7月月更

ES6---4个非常好用的运算符(??、??=、?.、?:)

Java学术趴

7月日更

以寡治众各个击破,超大文件分片上传之构建基于Vue.js3.0+Ant-desgin+Tornado6纯异步IO高效写入服务

刘悦的技术博客

tornado 异步 数据分片 Vue 3 文件上传

vue2升级vue3:composition api中监听路由参数改变

zhoulujun

Vue3 路由参数 参数监听 路由跳转

伺服驱动器在机器人上的研究与应用

优必选科技

机器人

当AI邂逅生命健康,华为云为他们搭建三座桥

脑极体

依法严厉打击违规自媒体运营者:净化自媒体行业迫在眉睫

石头IT视角

vue2升级vue3:vue3 hooks库选用

zhoulujun

Vue3 Hooks vueuse ahooks

聊聊接口性能优化的11个小技巧

苏三说技术

性能优化

【刷题记录】21. 合并两个有序链表

WangNing

7月月更

信息安全建设原则指导

穿过生命散发芬芳

7月月更 信息安全建设

vue2升级vue3:Vue Router报错,directly inside <transition> or <keep-a

zhoulujun

Vue3 router JSX tsx

高并发下如何保证数据库和缓存双写一致性?

苏三说技术

MySQL redis

哪吒 D1-H 测试 microbench

贾献华

7月月更

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