2010-11-07 62 views
2

在下一示例中的代码,˚F的.Net的#模式匹配常数

open System.Drawing 

let testColor c = 
    match c with 
    | Color.Black -> 1 
    | Color.White -> 0 
    | _ -> failwith "unexpected color" 

不编译。错误是Error 1 The field, constructor or member 'Black' is not defined

如何模式匹配.Net常量或以大写字母开头的枚举?

对于它的价值,编译器是“Microsoft(R)F#2.0 Interactive build 4.0.30319.1”。

回答

5

您无法与任意对象值进行模式匹配。使用if then elsewhen条件:

let testColor c = 
    match c with 
    | c when c = Color.Black -> 1 
    | c when c = Color.White -> 0 
    | _ -> failwith "unexpected color" 
+0

完美的答案。非常感谢。 – 2010-11-07 13:09:58

11

扩大在布赖恩的回答,模式匹配的情况不同禽兽不如switch语句。他们测试和分解输入结构而不是测试对象相等。但是如果在整个程序中经常使用黑色,白色和其他颜色的分割,Active Pattern可能是一种选择。对于一次性的“锅炉板”成本,他们让你定义你正在操作的对象周围的结构。例如,

open System.Drawing 
let (|Black|White|Other|) (color:Color) = 
    if color = Color.Black then Black 
    elif color = Color.White then White 
    else Other 

let testColor c = 
    match c with 
    | Black -> 1 
    | White -> 0 
    | Other -> failwith "unexpected color" 

或者,如果您同样只用黑白处理,但你总是希望黑评估为1和白色评估为0,那么你可以使用部分活动模式:

let (|KnownColor|_|) (color:Color) = 
    if color = Color.Black then Some(1) 
    elif color = Color.White then Some(0) 
    else None 

let testColor2 c = 
    match c with 
    | KnownColor i -> i 
    | _ -> failwith "unexpected color" 

更一般地,你甚至可以模拟使用通用的部分作用模式的switch语句:

let (|Equals|_|) (lhs) (rhs) = 
    if lhs = rhs then Some(lhs) else None 

let testColor3 c = 
    match c with 
    | Equals Color.Black _ -> 1 
    | Equals Color.White _ -> 0 
    | _ -> failwith "unexpected color" 

let testString c = 
    match c with 
    | Equals "Hi" _ -> 1 
    | Equals "Bye" _ -> 0 
    | _ -> failwith "unexpected string" 
+1

令人印象深刻。我忘记了活动模式,Brian的答案完成了这项工作,但这是如何使用它们的非常好的解释。 – 2010-11-07 15:23:43