处理枚举上的不完全模式匹配 [英] Working around incomplete pattern matching on enums

查看:122
本文介绍了处理枚举上的不完全模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在模式匹配时,有没有创造性的方式来解决.NET的弱枚举?我希望他们的功能类似于DU。这是我当前处理它的方式。任何更好的想法?

  [< RequireQualifiedAccess>] 
模块枚举=
允许意外<' ,'b,'c当'a:枚举<'b>> (value:'a):'c = //'
failwithf意外的枚举成员:%A:%Atypeof<'a>值//'


匹配值ConsoleSpecialKey.ControlC - > ()
| ConsoleSpecialKey.ControlBreak - > ()
| _ - > enum.unexpected value //没有这个,给出不完全模式匹配警告


解决方案

我认为这是一个很高的顺序,正是因为枚举是弱的。 ConsoleSpecialKey 是完整枚举的一个很好的例子,其中 ControlC ControlBreak 是唯一有意义的值。但是我们有一个问题,你可以将任何整数强制到一个 ConsoleSpecialKey !中:

  let x = ConsoleSpecialKey.Parse(typeof< ConsoleSpecialKey>32):?> ConsoleSpecialKey 

所以你提供的模式真的不完整,真的需要处理。

更不用说像$ System.Reflection.BindingFlags 这样的更复杂的枚举,它们用于位掩码,但不能区分从简单的枚举中输入信息,进一步使图片复杂化 编辑:实际上,@ildjarn指出标志属性来区分完整的和位掩码的枚举,尽管编译器不会阻止您在没有标记此属性的枚举上使用按位操作,再次显示弱点的枚举



但是,如果您正在使用特定的完整枚举,如 ConsoleSpecialKey 并且写出最后一个不完整的模式匹配的情况,所有的时间是真正的bug你,你可以总是鞭打一个完整的主动模式n:

  let(| ControlC | ControlBreak |)value = 

匹配值| ConsoleSpecialKey.ControlC - > ControlC
| ConsoleSpecialKey.ControlBreak - > ControlBreak
| _ - >枚举预期值

//完成
匹配值与
| ControlC - > ()
| ControlBreak - > ()

然而,这类似于简单地将不完整的模式匹配大小写处理,并且抑制了警告。我认为你目前的解决方案是不错的,只要坚持下去,你会很好。


Are there any creative ways to work around .NET's "weak" enums when pattern matching? I'd like them to function similarly to DUs. Here's how I currently handle it. Any better ideas?

[<RequireQualifiedAccess>]
module Enum =
  let unexpected<'a, 'b, 'c when 'a : enum<'b>> (value:'a) : 'c = //'
    failwithf "Unexpected enum member: %A: %A" typeof<'a> value //'

match value with
| ConsoleSpecialKey.ControlC -> ()
| ConsoleSpecialKey.ControlBreak -> ()
| _ -> Enum.unexpected value //without this, gives "incomplete pattern matches" warning

解决方案

I think in general this is a tall order, exactly because enums are "weak". ConsoleSpecialKey is a good example of a "complete" enum where ControlC and ControlBreak, which are represented by 0 and 1 respectively, are the only meaningful values it can take on. But we have a problem, you can coerce any integer into a ConsoleSpecialKey!:

let x = ConsoleSpecialKey.Parse(typeof<ConsoleSpecialKey>, "32") :?> ConsoleSpecialKey

So the pattern you gave really is incomplete and really does needs to be handled.

(not to mention more complex enums like System.Reflection.BindingFlags, which are used for bitmasking and yet indistinguishable through type information from simple enums, further complicating the picture edit: actually, @ildjarn pointed out that the Flags attribute is used, by convention, to distinguish between complete and bitmask enums, though the compiler won't stop you from using bitwise ops on an enum not marked with this attribute, again revealing the weakens of enums).

But if you are working with a specific "complete" enum like ConsoleSpecialKey and writing that last incomplete pattern match case all the time is really bugging you, you can always whip up a complete active pattern:

let (|ControlC|ControlBreak|) value =
    match value with
    | ConsoleSpecialKey.ControlC -> ControlC
    | ConsoleSpecialKey.ControlBreak -> ControlBreak
    | _ -> Enum.unexpected value

//complete
match value with
| ControlC -> ()
| ControlBreak -> ()

However that's akin to simply leaving the incomplete pattern match case unhandled and suppressing the warning. I think your current solution is nice and you would be good just to stick with it.

这篇关于处理枚举上的不完全模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆