F# 输出参数和值类型

F# out parameters and value types

如果我传递对对象的引用,但不接受结构或原语,则以下 f# 函数工作得很好:

let TryGetFromSession (entryType:EntryType, key, [<Out>]  outValue: 'T byref) =
    match HttpContext.Current.Session.[entryType.ToString + key] with 
             | null -> outValue <- null; false
             | result -> outValue <- result :?> 'T; true

如果我尝试从 C# 调用它:

bool result = false;
TryGetFromSession(TheOneCache.EntryType.SQL,key,out result)

我得到 The Type bool must be a reference type in order to use it as a parameter 有没有办法让 F# 函数同时处理这两个问题?

问题是 outValue <- null 中的 null 值将类型 'T 限制为引用类型。如果它具有 null 作为有效值,则它不能是值类型!

您可以改用 Unchecked.defaultOf<'T> 来解决这个问题。这与 C# 中的 default(T) 相同,它 returns null(对于引用类型)或 empty/zero 值类型的值。

let TryGetFromSession (entryType:EntryType, key, [<Out>]  outValue: 'T byref) =
    match HttpContext.Current.Session.[entryType.ToString() + key] with 
    | null -> outValue <- Unchecked.defaultof<'T>; false
    | result -> outValue <- result :?> 'T; true

我仍然认为这不是 "pretty"/idomatic F# 代码,可能会用以下内容做一些更多的仪式:

let myCast<'T> o = 
 match box o with
 | :? 'T as r -> Some(r)
 | _ -> None


let GetFromSession<'T> entryType key = 
 match HttpContext.Current.Session.[entryType.ToString + key] with 
 | null -> None
 | r -> myCast<'T> r

这也是一种 "safer" 并且将(应该?)不抛出任何异常,并且它删除了 F# 中的空值。在 C# 中它会 return 并且工作正常,但是 None 被 return 编辑为 null,如果有结果,那么它会是 Some ;-)

请注意,以上代码未经过测试,未运行任何设置甚至编译,因此将其视为伪代码。它甚至可能还有其他问题...

同时检查: https://msdn.microsoft.com/en-us/library/dd233220.aspxhttp://fsharpforfunandprofit.com/posts/match-expression/

最后一个 link 特别是:子类型匹配

附带说明一下,我不喜欢缺少对从 HttpContext 到 Session 的整个层次结构的非空检查,但这可能只是我...

使用 None/Some

更新一些 C# 代码
var x = GetFromSession<MyTypeInSession>(entryType, key)?.Value??defaultValue;

绝对没有必要完全用阿拉伯语,从右到左,从下到上阅读如果和但是的金字塔结构,没有糖果或坚果,用于空检查等令人作呕。

再次将代码视为伪代码...