AICon上海|与字节、阿里、腾讯等企业共同探索Agent 时代的落地应用 了解详情
写点什么

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

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

关注

评论

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

Spring Boot核心技术之Restful映射以及源码的分析,springboot启动原理通俗

Java 程序员 后端

Set集合无法去重相同内容的父类对象和子类对象的问题解决

Java 程序员 后端

SonarQube检测出的bug、漏洞以及异味的修复整理,mysql基础知识

Java 程序员 后端

Spring Cloud Gateway实战之二:更多路由配置方式,阿里面试java准备

Java 程序员 后端

Redis-生产架构选型解决方案,java开发架构师

Java 程序员 后端

Redis-用的很溜,了解过它用的什么协议吗?,3天拿到网易Java岗offer

Java 程序员 后端

Redis总结,学Java必看书籍

Java 程序员 后端

Redis到底能干什么?又不能干什么呢?,kettle面试题

Java 程序员 后端

SCA Sentinel 分布式系统的流量防卫兵,春招我借这份PDF的复习思路

Java 程序员 后端

seata-golang 一周年回顾,java面试准备内容

Java 程序员 后端

redis 在微服务领域的贡献,java制作微信小程序教程

Java 程序员 后端

Redis高可用篇:Cluster集群能支持的数据量有多大?,再不了解你就out啦

Java 程序员 后端

Spring Boot 项目如何做性能监控?,javase教程书

Java 程序员 后端

Redis不只是get set,八种数据类型及应用场景分析,java技术栈面试题

Java 程序员 后端

Redis该怎么学?其实很简单,这份学习路线,mybatis架构梳理

Java 程序员 后端

Socket和ServerSocket的简单介绍及例子,mongodb教程导入外部数据

Java 程序员 后端

Redis哨兵原理,我忍你很久了!,java面试视频百度云

Java 程序员 后端

SonarQube,SonarLint检测代码修复问题汇总归纳,2021京东最新Java面试真题解析

Java 程序员 后端

Spring Boot 谷粒学院、谷粒商城项目问题汇总,springboot源码视频

Java 程序员 后端

Servlet的Cookie和Session机制,面试谈谈对springboot的理解

Java 程序员 后端

set集合,挑战华为社招

Java 程序员 后端

Spring Boot面试题(2020最新版),2021我的Java大厂面试之旅

Java 程序员 后端

Redis入门到五大类型实现,java基础知识点大全

Java 程序员 后端

Redis面试题汇总,mysql调优面试题

Java 程序员 后端

RocketMQ 5,学习linux系统管理

Java 程序员 后端

RestFul API 统一格式返回 + 全局异常处理,linux系统编程视频教程

Java 程序员 后端

Serverless Devs 的官网是如何通过 Serverless Devs 部署的

Java 程序员 后端

Sleuth服务跟踪大厂高频面试题:整合-Zipkin,java面向对象程序开发及实战答案

Java 程序员 后端

Redis分布式基石——主从复制技术详述,Java黑科技实现原理揭秘

Java 程序员 后端

Redis精通系列——LRU算法详述(Least Recently Used - 最近最少使用)

Java 程序员 后端

Redis:看完就比常人多会三种类型实战,可以拿去炫耀了

Java 程序员 后端

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