与ref传递的参数进行互操作
本文关键字:互操作 参数 ref | 更新日期: 2023-09-27 18:18:33
我正在尝试调用一个已经存在的库的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)
表示将函数转换为代数数据类型,目的是使非法状态不可表示。
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
相同的问题)
在f#中ref
不是一个关键字,而是一个创建参考单元格的函数。因此,Xlsx.TestSave(proposed, ref filename, ref save_log)
将两个新创建的ref
引用单元格(指向mutable string
的值)传递给TestSave
,进而将ref
单元格更改为指向string
分配的任何值。不幸的是,这是无法从外部观察到的,因为没有任何指向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)
和完全摆脱ref
s,因为f# 4.0简化了mutable
s与ref
的使用。
此外,我尽量避免在简单的bool
上使用match
,传统的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)
显然,使用out
代替ref
更好,但是对于"…一个已经存在的库…"你可能没有这个选择
如果你在c#端使用out
而不是ref
,那么你应该可以这样做:
let getUserFile(proposed) : UserFile =
match Xlsx.TestSave proposed with
| true, filename, _ -> FileResult(filename)
| false, _, save_log -> ErrorMsg(save_log)
,因为后面的out
参数可以被视为具有实际结果类型的元组。