写点什么

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

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

关注

评论

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

实战 | Vue + Element UI 页面创建

简爱W

Java 架构师

netty案例,netty4.1中级拓展篇四《Netty传输文件、分片发送、断点续传》

小傅哥

Netty 小傅哥

netty案例,netty4.1中级拓展篇五《基于Netty搭建WebSocket,模仿微信聊天页面》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇十《关于ChannelOutboundHandlerAdapter简单使用》

小傅哥

Netty 小傅哥

程序开发中的持续集成、持续交付、持续部署

石云升

持续集成 持续交付 持续部署 自动化部署

在java中使用SPI创建可扩展的应用程序

程序那些事

Java spi 可扩展程序 可扩展应用

netty案例,netty4.1基础入门篇零《初入JavaIO之门BIO、NIO、AIO实战练习》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇七《嗨!NettyClient》

小傅哥

Netty 小傅哥

netty案例,netty4.1基础入门篇九《自定义编码解码器,处理半包、粘包数据》

小傅哥

Java Netty

netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》

小傅哥

Java Netty

netty案例,netty4.1基础入门篇二《NettyServer接收数据》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇三《NettyServer字符串解码器》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇四《NettyServer收发数据》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇六《NettyServer群发消息》

小傅哥

Java Netty 小傅哥

PHP浮点数精度损失问题

架构精进之路

php 弱类型语言

[租房]刚步入社会的小萌新,休想坑小妹妹,安排!

我是程序员小贱

netty案例,netty4.1基础入门篇十二《简单实现一个基于Netty搭建的Http服务》

小傅哥

Java Netty

一把年龄,技术一般,怎么去面试

escray

学习 面试

netty案例,netty4.1中级拓展篇三《Netty传输Java对象》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1基础入门篇一《嗨!NettyServer》

小傅哥

Java Netty

netty案例,netty4.1基础入门篇五《NettyServer字符串编码器》

小傅哥

Java Netty

netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理、编码解码处理、收发数据方式》

小傅哥

Netty 小傅哥

netty案例,netty4.1基础入门篇十一《netty udp通信方式案例Demo》

小傅哥

Java Netty

Stream 流

HeGuang

Java

netty案例,netty4.1中级拓展篇二《Netty使用Protobuf传输数据》

小傅哥

Java Netty 小傅哥

netty案例,netty4.1中级拓展篇六《SpringBoot+Netty+Elasticsearch收集日志信息数据存储》

小傅哥

Java Netty

netty案例,netty4.1中级拓展篇七《Netty请求响应同步通信》

小傅哥

Java Netty 小傅哥

理论 | 三天两夜,万字长文,吃透TCP/IP

简爱W

Java TCP

没有亮点的简历,要用详历来弥补

escray

学习 面试 简历

LeetCode题解:11. 盛最多水的容器,for循环双指针,JavaScript,详细注释

Lee Chen

大前端 LeetCode

世界很大,我想去看看

escray

学习 面试

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