我检索给定类型的TryParse方法,如下所示:

open System.Reflection

let stringParser<'T> =
    typeof<'T>.GetMember("TryParse")
    |> Seq.cast<MethodBase>
    |> Seq.choose (fun m ->
        let parameterTypes =
            m.GetParameters()
            |> Array.map (fun p -> (p.ParameterType, p.Attributes))
        if parameterTypes =
            [| (typeof<string>, ParameterAttributes.None)
            ;  (typeof<'T>.MakeByRefType(), ParameterAttributes.Out) |] then Some m
        else None)
    |> Seq.exactlyOne

现在的问题是如何在调用该方法时提供第二个参数,该方法将解析结果作为引用.mutable变量[1]会导致‘type instantiation Engine a byref type’编译错误,而ref变量[2]会在运行时导致类型不匹配(此处给出,例如uint16):

let fromString<'T> (s: string) =
    // [1]
    //let mutable parseResult = Unchecked.defaultof<'T>
    // Using '&parseResult' gives:
    // A type instantiation involves a byref type. This is not permitted by the rules of Common IL
    
    // [2]
    //let parseResult = ref (Unchecked.defaultof<'T>)
    // Using 'parseResult' produces a runtime exception:
    // System.ArgumentException: Object of type 'Microsoft.FSharp.Core.FSharpRef`1[System.UInt16]' cannot be converted to type 'System.UInt16&'.

    // How to declare parseResult to retrieve the method result?
    let potentialResult = stringParser<'T>.Invoke(null, [|s; parseResult|])
    match potentialResult with
    | :? bool as boolResult ->
        if boolResult then Some (parseResult)
        else None
    | _ -> None

推荐答案

创建一个包含2个元素的数组,并使用第二个元素而不是parseResult:

let fromString<'T> (s: string) =
    let ps : obj[] = [|s; null|]
    let potentialResult = stringParser<'T>.Invoke(null, ps)
    match potentialResult with
    | :? bool as boolResult ->
        if boolResult then Some (ps[1] :?> 'T)
        else None
    | _ -> None

请注意,在添加了通用数学支持和静态抽象接口成员的.NET 7中,您只需利用IParsable<T>接口:

let fromString1<'T when 'T :> IParsable<'T>> (s: string) =
    let mutable parseRes = Unchecked.defaultof<'T>
    let parsed = 'T.TryParse(s, CultureInfo.InvariantCulture, &parseRes)
    match parsed with
    | true -> Some(parseRes)
    | _ -> None

.net相关问答推荐

API响应返回null错误. NET MAUI

.NET发布的应用程序运行与开发不同的端口

为什么.Net 8.0.100是预览版?

为什么Regex.Escape支持数字符号和空格?

如何在PowerShell中隐藏任务延迟输出?

MassTransit RespondAsync 无法返回空值

Erlang 的让它崩溃的哲学 - 适用于其他地方吗?

为什么 Any() 不适用于 c# null 对象

如何获取 Sql Server 数据库中所有模式的列表

发布版本中的 Debug.WriteLine

是什么让 Enum.HasFlag 这么慢?

什么决定了 Path.GetTempPath() 的返回值?

msbuild,定义条件编译符号

使用 .NET 中的代码更改桌面墙纸

Dapper 是否支持 SQL 2008 表值参数?

单元测试 C# 保护方法

Visual Studio 类图不显示关系

判断任意字符串是否为有效文件名的最简单方法

如何在我的机器上找到 fuslogvw.exe?

判断数据表中是否包含空值的最佳方法