解决枚举上不完整的模式匹配 [英] Working around incomplete pattern matching on enums

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

问题描述

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

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

推荐答案

我认为总的来说这是一项艰巨的任务,正是因为枚举是弱项".ConsoleSpecialKey 是完整"枚举的一个很好的例子,其中 ControlCControlBreak 分别由 0 和 1 表示,是唯一有意义的它可以承担的价值.但是我们有一个问题,你可以将任何整数强制转换为 ConsoleSpecialKey!:

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.

(更不用说像 System.Reflection.BindingFlags 这样更复杂的枚举,它们用于位掩码,但通过类型信息与简单枚举无法区分,进一步使情况复杂化实际上,@ildjarn 指出使用了 Flags 属性,按照惯例,要区分完整枚举和位掩码枚举,尽管编译器不会阻止您在未标记此属性的枚举上使用按位操作,再次揭示枚举的弱点).

(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).

但是,如果您正在使用像 ConsoleSpecialKey 这样的特定完整"枚举,并且一直在编写最后一个不完整的模式匹配案例真的很困扰您,那么您总是可以创建一个完整的活动模式:

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天全站免登陆