写点什么

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

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

关注

评论

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

数据技术大融合,HSTAP数据库有多少想象空间?

MatrixOrigin

MatrixOrigin MatrixOne HSTAP

【杂谈】网络协议(二)

自然

网络层 8月月更

音频技术的下一个“热点”,会出现在哪个领域?丨一期一会 • 音频工程师专场

声网

人工智能 音频

每日一 R「12」数据结构(三)哈希表

Samson

8月月更 ​Rust

kubernetes ansible快速构建

CTO技术共享

开源一夏 | Foundation对于模态框以及Subsystems的深入运用的理解心得

恒山其若陋兮

开源 8月月更

C++多态案例(三)-电脑组装

CtrlX

c c++ 面向对象 8月月更

关于TAE(Transactional Analytical Engine)的那些事

MatrixOrigin

MatrixOne 矩阵起源 MatirxOrigin TAE

Spring 全家桶之 Spring Security(四)

小白

8月月更

灵魂拷问:你精神内耗了吗?由TA来治愈吧

白洞计划

Java开发微信公众号初体验

源字节1号

前端开发 后端开发 小程序开发

Spring 全家桶之 Spring Security(三)

小白

8月月更

Kubernetes Argo Rollouts高级的部署能力

CTO技术共享

Spring 全家桶之 Spring Security(五)

小白

8月月更

用golang官方Docker镜像运行项目

程序员欣宸

golang 8月月更

[教你做小游戏] 用177行代码写个体验超好的五子棋

HullQin

CSS JavaScript html 前端 8月月更

多模态算法在视频理解中的应用

之家技术

人工智能 算法 视频 多模态

leetcode 503. Next Greater Element II 下一个更大元素 II(中等)

okokabcd

LeetCode 算法与数据结构

NOIP考试注意事项

工程师日月

8月月更

gateway网关

急需上岸的小谢

8月月更

网络架构设计概要

阿泽🧸

8月月更

【算法实践】| 一步步带你实现寻找最大公约数

迷彩

数学 算法解析 算法实践 8月月更 最大公约数

基于时间戳的日志回放引擎

FunTester

七种常见的IPv6网络攻击

穿过生命散发芬芳

ipv6 8月月更 网络攻击

并行接口8255A简介

乌龟哥哥

8月月更

数据治理(七):Atlas搭建启动

Lansonli

数据治理 8月月更

Spring 全家桶之 Spring Security(二)

小白

8月月更

字典服务的设计与管理

Java 架构

Kubernetes伟大的未来

CTO技术共享

头脑风暴:判断子序列

HelloWorld杰少

算法 LeetCode 8月月更

Spring 全家桶之 Spring Security(一)

小白

8月月更

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