mam*_*mcx 5 f# types pattern-matching
我知道如何在对象的类型上进行匹配,但是如何直接在类型对象上进行匹配?
这不起作用:
let toType = p.PropertyType
match toType with
| System.Enum ->
| System.Int32 ->
Run Code Online (Sandbox Code Playgroud)
PD:是的,我需要匹配类型。我没有物体,因为我正在反思
您无法对其System.Type自身进行匹配,因为它不是 F# 可解构类型。同样的方式你也无法匹配,例如 onStreamReader或 onStringBuilder等。
但你可以很好地比较类型,例如:
if t = typeof<Enum> then ...
elif t = typeof<Int32> then ...
else ...
Run Code Online (Sandbox Code Playgroud)
但是,请记住,这只会给您带来严格的平等。它不会给你子类型。例如,typeof<DayOfWeek> <> typeof<Enum>。
为了检查子类型,请使用以下Type.IsAssignableFrom方法:
if typeof<Enum>.IsAssignableFrom t then ...
elif typeof<Int32>.IsAssignableFrom t then ...
else ...
Run Code Online (Sandbox Code Playgroud)
(请注意,对于Int32简单的比较就足够了,因为它Int32是密封类型,所以它不能有子类型;但IsAssignableFrom为了保持一致性,我仍然保留在那里)
如果你真的想使用match语法,你总是可以让自己成为一个活动模式。
不幸的是,您不能在模式中使用尖括号(无论出于何种原因),所以这match x with IsType typeof<Enum>是不可能的。但是您可以在模式中使用引号,并且引号中可以包含尖括号,因此您可以这样做match x with IsType <@ typeof<Enum> @>。不幸的是,这意味着活动模式将相当复杂并且性能不那么好:
let (|IsType|_|) (a: FSharp.Quotations.Expr<System.Type>) (t: System.Type) : unit option =
match a with
| FSharp.Quotations.Patterns.Call (None, m, []) when m.Name = "TypeOf" ->
let testAgainst = m.GetGenericArguments().[0]
if testAgainst.IsAssignableFrom t
then Some()
else None
| _ ->
None
match t with
| IsType <@ typeof<Enum> @> -> "enum"
| IsType <@ typeof<Int32> @> -> "int"
| _ -> "don't know"
Run Code Online (Sandbox Code Playgroud)
这是相当重要的,所以我不推荐它。只是作为一种心理锻炼:-)