与 ref 传递的参数互操作
Interop with parameters passed by ref
我正在尝试调用现有库的 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)
意味着将函数转换为具有objective的代数数据类型,以构成非法状态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
的问题相同)
在 F# 中,ref
不是关键字,而是创建引用单元格的函数。 Xlsx.TestSave(proposed, ref filename, ref save_log)
因此将两个新创建的 ref
erence 单元格(指向 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)
并从 F# 4.0 simplified the use of mutable
s vs. ref
.
开始完全删除 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)
显然, 更好,但是对于“...一个已经存在的库...”,您可能没有那个选择。
如果您在 C# 端使用 out
而不是 ref
,那么您应该可以这样做:
let getUserFile(proposed) : UserFile =
match Xlsx.TestSave proposed with
| true, filename, _ -> FileResult(filename)
| false, _, save_log -> ErrorMsg(save_log)
因为可以将尾随 out
参数视为具有实际结果类型的元组。
我正在尝试调用现有库的 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)
意味着将函数转换为具有objective的代数数据类型,以构成非法状态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
的问题相同)
在 F# 中,ref
不是关键字,而是创建引用单元格的函数。 Xlsx.TestSave(proposed, ref filename, ref save_log)
因此将两个新创建的 ref
erence 单元格(指向 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)
并从 F# 4.0 simplified the use of mutable
s vs. ref
.
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)
显然,
如果您在 C# 端使用 out
而不是 ref
,那么您应该可以这样做:
let getUserFile(proposed) : UserFile =
match Xlsx.TestSave proposed with
| true, filename, _ -> FileResult(filename)
| false, _, save_log -> ErrorMsg(save_log)
因为可以将尾随 out
参数视为具有实际结果类型的元组。