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.aspx
和
http://fsharpforfunandprofit.com/posts/match-expression/
最后一个 link 特别是:子类型匹配
附带说明一下,我不喜欢缺少对从 HttpContext 到 Session 的整个层次结构的非空检查,但这可能只是我...
使用 None/Some
更新一些 C# 代码
var x = GetFromSession<MyTypeInSession>(entryType, key)?.Value??defaultValue;
绝对没有必要完全用阿拉伯语,从右到左,从下到上阅读如果和但是的金字塔结构,没有糖果或坚果,用于空检查等令人作呕。
再次将代码视为伪代码...
如果我传递对对象的引用,但不接受结构或原语,则以下 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.aspx 和 http://fsharpforfunandprofit.com/posts/match-expression/
最后一个 link 特别是:子类型匹配
附带说明一下,我不喜欢缺少对从 HttpContext 到 Session 的整个层次结构的非空检查,但这可能只是我...
使用 None/Some
更新一些 C# 代码var x = GetFromSession<MyTypeInSession>(entryType, key)?.Value??defaultValue;
绝对没有必要完全用阿拉伯语,从右到左,从下到上阅读如果和但是的金字塔结构,没有糖果或坚果,用于空检查等令人作呕。
再次将代码视为伪代码...