[英]Interop with parameters passed by ref
I'm trying to call a C# function of an already existing library (and I don't have time to port the whole library to F#) 我正在尝试调用现有库的C#函数(并且我没有时间将整个库移植到F#)
namespace ExportLib
{
public static class Xlsx
{
public static bool TestSave(string proposed, ref string filename, ref string save_log) {
from an F# code 从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)
meant to transform the function into algebraic data types with the objective to make illegal states unrepresentable . 意味着功能转化为代数数据类型,其目标是使非法状态不可表示 。
type UserFile =
// The value here is the file path.
| FileResult of string
// The value here is the error msg.
| ErrorMsg of string
My issue is that the mutable
F# filename
remains unchanged despite it is assigned in the C# function (same problem with out string
instead of ref string
) 我的问题是,尽管在C#函数中分配了
mutable
F# filename
但filename
保持不变(用out string
代替ref string
同样的问题)
In F# ref
is not a keyword but a function creating a reference cell. 在F#中,
ref
不是关键字,而是创建参考单元的函数。 Xlsx.TestSave(proposed, ref filename, ref save_log)
thus passes two newly created ref
erence cells (pointing to mutable string
values) into TestSave
which in turn changes the ref
cell to point to whatever string
is assigned. Xlsx.TestSave(proposed, ref filename, ref save_log)
因此将两个新创建的ref
单元格(指向mutable string
值) TestSave
到TestSave
中,后者又将ref
单元格更改为指向分配的任何string
。 Unfortunately, this is not observable from the outside, as there's nothing pointing to the ref
cells. 不幸的是,这是无法从外部观察到的,因为没有任何指向
ref
单元的内容。 One approach is: 一种方法是:
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)
As noted by @kvb you can also use 如@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)
and get rid of ref
s altogether since F# 4.0 simplified the use of mutable
s vs. ref
. 并完全摆脱了
ref
因为F#4.0简化了mutable
s与ref
。
Also, I try to avoid match
ing on a simple bool
, traditional if then else
is shorter: 另外,我尽量避免
match
上简单的ING 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)
Obviously, using out
instead of ref
is even better, but for "... an already existing library ..." you might not have that choice. 显然, 使用
out
而不是ref
甚至更好,但是对于“ ...一个已经存在的库...”,您可能没有这种选择。
If you use out
instead of ref
on the C# side, then you should be able to just do this instead: 如果您在C#端使用
out
而不是ref
,那么您应该能够做到这一点:
let getUserFile(proposed) : UserFile =
match Xlsx.TestSave proposed with
| true, filename, _ -> FileResult(filename)
| false, _, save_log -> ErrorMsg(save_log)
because trailing out
parameters can be treated as a tuple with the actual result type. 因为后
out
参数可以被视为与实际结果类型的元组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.