我正在将一个C#库重写为F#,我需要翻译以下代码
bool success;
instance.GetValue(0x10, out success);
Run Code Online (Sandbox Code Playgroud)
outF#中关键字的等价物是什么?
pho*_*oog 16
既不是wasatz的答案也不是Max Malook的答案都是完整的.使用out参数调用方法有三种方法.第二种和第三种方式也适用于ref参数.
对于示例,假设以下类型:
open System.Runtime.InteropServices //for OutAttribute
type SomeType() =
member this.GetValue (key, [<Out>] success : bool byref) =
if key = 10 then
success <- true
"Ten"
else
success <- false
null
Run Code Online (Sandbox Code Playgroud)
还假设我们有一个该类型的实例:
let o = SomeType()
Run Code Online (Sandbox Code Playgroud)
您可以让F#编译器通过使用返回值对其进行元组处理来处理out参数:
let result1, success1 = o.GetValue 10
let result2, success2 = o.GetValue 11
Run Code Online (Sandbox Code Playgroud)
在F#交互式运行上面的行产生
val success1 : bool = true
val result1 : string = "Ten"
val success2 : bool = false
val result2 : string = null
Run Code Online (Sandbox Code Playgroud)
您可以使用可变值,并使用&运算符传递其地址:
let mutable success3 = false
let result3 = o.GetValue (10, &success3)
let mutable success4 = false
let result4 = o.GetValue (11, &success4)
Run Code Online (Sandbox Code Playgroud)
在F#interactive中,结果是
val mutable success3 : bool = true
val result3 : string = "Ten"
val mutable success4 : bool = false
val result4 : string = null
Run Code Online (Sandbox Code Playgroud)
当您委托给另一个方法时,此选项最好,因为您可以将调用方法的out参数直接传递给被调用的方法.例如,如果要实现包装器IDictionary<_,_>,则可以将TryGetValue方法编码为
//...
interface IDictionary<'TKey, 'TValue> with
member this.TryGetValue (key, value) = inner.TryGetValue (key, &value)
//...
Run Code Online (Sandbox Code Playgroud)
您可以使用参考单元格:
let success5 = ref false
let result5 = o.GetValue (10, success5)
let success6 = ref false
let result6 = o.GetValue (11, success6)
Run Code Online (Sandbox Code Playgroud)
输出:
val success5 : bool ref = {contents = true;}
val result5 : string = "Ten"
val success6 : bool ref = {contents = false;}
val result6 : string = null
Run Code Online (Sandbox Code Playgroud)
注意不要ref像在C#中那样使用关键字作为输入/输出参数.例如,以下内容不会产生所需的结果:
let success7 = false
let result7 = o.GetValue (10, ref success7)
Run Code Online (Sandbox Code Playgroud)
输出:
val success7 : bool = false
val result7 : string = "Ten"
Run Code Online (Sandbox Code Playgroud)
为什么success7保持价值false?因为success7是一个不可变的变量.
在C#中,ref请注意您将对变量的引用作为参数的ref参数传递的事实.它只是作为保险,调用者的程序员知道变量可以被被调用的方法修改.但是,在F#中,ref创建一个新的引用单元格,其中包含以下表达式的值的副本.
在这种情况下,我们创建一个引用单元格,其中包含从success7变量复制的值,但不会将该新引用单元格分配给任何变量.然后,我们将该引用单元传递给GetValue方法,该方法修改引用单元格的内容.因为调用方法没有指向修改的单元格的变量,所以它无法读取引用单元格的新值.
你可能应该返回一个选项或一个元组.因为F#具有模式匹配,所以您实际上不需要输出参数,因为有更好的方法可以从函数返回多个值.
所以,这样的事情会更加惯用
let (value, success) = instance.GetValue(0x10)
Run Code Online (Sandbox Code Playgroud)
其中instance.GetValue是一个
unit -> ('a, bool)
Run Code Online (Sandbox Code Playgroud)
或者您可以返回一个选项并执行类似的操作
match instance.GetValue(0x10) with
| Some value -> doStuff value
| None -> failwith "Oops!"
Run Code Online (Sandbox Code Playgroud)
小智 5
您必须使用参考单元格.
let success = ref false
instance.GetValue(0x10, success)
// access the value
!success
Run Code Online (Sandbox Code Playgroud)