与 ref 传递的参数进行互操作

Interop with parameters passed by ref

提问人: 提问时间:11/18/2016 更新时间:11/19/2016 访问量:123

问:

我正在尝试调用现有库的 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

我的问题是,尽管 F# 是在 C# 函数中分配的,但它保持不变(同样的问题不是mutablefilenameout stringref string)

c# f# 互操作 可变 裁判

评论


答:

4赞 CaringDev 11/18/2016 #1

在 F# 中,不是关键字,而是创建引用单元格的函数。 因此,传递两个新创建的 erence 单元格(指向值),进而将单元格更改为指向分配的任何内容。不幸的是,这无法从外部观察到,因为没有任何东西指向细胞。一种方法是:refXlsx.TestSave(proposed, ref filename, ref save_log)refmutable stringTestSaverefstringref

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)

并完全摆脱 s,因为 F# 4.0 简化了可变s 与 ref 的使用ref

另外,我尽量避免使用简单的、繁体的更短的:matchboolif 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 会更好,但对于“......一个已经存在的图书馆......”你可能没有那个选择。

评论

1赞 kvb 11/18/2016
没错。或者,您应该能够保持声明原样,并使用 和 传递引用。&filename&save_log
2赞 kvb 11/19/2016 #2

如果使用 而不是在 C# 端,则应该能够执行以下操作:outref

let getUserFile(proposed) : UserFile =
    match Xlsx.TestSave proposed with
    | true, filename, _  -> FileResult(filename)
    | false, _, save_log -> ErrorMsg(save_log)

因为尾随参数可以被视为具有实际结果类型的元组。out