我试图调用现有库的C#函数(我没有时间将整个库移植到F#)
namespace ExportLib
{
public static class Xlsx
{
public static bool TestSave(string proposed, ref string filename, ref string save_log) {
来自F#代码
let getUserFile(proposed) : UserFile =
let mutable filename = ""
let mutable save_log = ""
match Xlsx.TestSave(proposed, ref filename, ref save_log) with
| true -> FileResult(filename)
| false -> ErrorMsg(save_log)
意味着将函数转换为代数数据类型,目的是使非法状态unrepresentable。
type UserFile =
// The value here is the file path.
| FileResult of string
// The value here is the error msg.
| ErrorMsg of string
我的问题是,mutable
F#filename
保持不变,尽管它是在C#函数中分配的(与out string
相同而不是ref string
同样存在)
答案 0 :(得分:4)
在F#ref
中不是关键字,而是创建引用单元格的函数。 Xlsx.TestSave(proposed, ref filename, ref save_log)
因此将两个新创建的ref
个单元格(指向mutable string
值)传递到TestSave
,这又将ref
单元格更改为指向string
1}}已分配。不幸的是,这不是从外部观察到的,因为没有任何指向ref
细胞的东西。一种方法是:
let getUserFile(proposed) : UserFile =
let filename = ref ""
let save_log = ref ""
match Xlsx.TestSave(proposed, filename, save_log) with
| true -> FileResult(!filename)
| false -> ErrorMsg(!save_log)
如@kvb所述,您也可以使用
let getUserFile(proposed) : UserFile =
let mutable filename = ""
let mutable save_log = ""
match Xlsx.TestSave(proposed, &filename, &save_log) with
| true -> FileResult(filename)
| false -> ErrorMsg(save_log)
并自F# 4.0 simplified the use of mutable
s vs. ref
以来完全摆脱ref
。
此外,我尝试避免match
简单bool
,传统if then else
更短:
let getUserFile(proposed) : UserFile =
let mutable filename = ""
let mutable save_log = ""
if Xlsx.TestSave(proposed, &filename, &save_log) then
FileResult(filename)
else
ErrorMsg(save_log)
显然,using out
instead of ref
甚至更好,但对于" ...已经存在的库..."你可能没有这个选择。
答案 1 :(得分:2)
如果您在C#端使用out
而不是ref
,那么您应该可以这样做:
let getUserFile(proposed) : UserFile =
match Xlsx.TestSave proposed with
| true, filename, _ -> FileResult(filename)
| false, _, save_log -> ErrorMsg(save_log)
因为尾随out
参数可以被视为具有实际结果类型的元组。