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








 
    
评论