F# — использовать методы C# без параметра out (внутри массивов и с пустым возвратом)

Я прочитал f-equivalent-of-cs-out, но все же я не могу заставить его работать для моего случая (самое простое решение/синтаксис).

У меня есть этот метод в проекте С#:

//<Project Sdk="Microsoft.NET.Sdk">
//<TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>

public static void ABC(out byte[] a, out byte[] b, byte[] c)
{
    var aaa = new byte[10];
    var bbb = new byte[10];            
    a = aaa;
    b = bbb;
}

Теперь я хочу использовать его в проекте F#: я использую FSharp.Core 4.7.2

(* <Project Sdk="Microsoft.NET.Sdk">
   <TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks> *)

let a,b = ABC(c)

Я имитирую синтаксис TryParse, и это компилируется без ошибок:

let success, number = System.Int32.TryParse("0")

Компилятор на моем вызове ABC(c) жалуется на то, что подпись запрашивает 3 параметра, а не 1.
По сравнению с TryParse я вижу 2 отличия:

  • Не возвращает void
  • Он использует объекты массива

Компилятор принимает такой синтаксис:

let a = Array.empty<byte>
let b = Array.empty<byte>
ABC(ref a, ref b, c) 

но:

  1. Я думаю, что здесь неправильно использовать ref, не таким образом (потому что a и b не изменяемы)
  2. Я хотел бы использовать чистый синтаксис, похожий на TryParse, и Я ХОЧУ знать, почему он здесь не работает

Я могу изменить код проекта C#, но замена всех параметров out в этом проекте будет вторым шагом и, возможно, новым вопросом, если у меня возникнут трудности или сомнения.

[Обновление: положение параметра]

Я немного поигрался с этим и, кажется, нашел, когда простой синтаксис (без передачи параметров ref) нарушается.

public static void TryParseArray(string input, out int[] result) {
    result = new int[0];
}

public static void TryParseArray_2(out int[] result, string input) {
    result = new int[0];
}
let arr = csharp.TryParseArray("a")            // OK
let arr = csharp.TryParseArray_2("a")          // ERROR

Похоже, что параметр out должен быть в конце (= за ним не следуют обычные параметры) в методах C#, чтобы F# мог использовать их как возвращаемый кортеж.


person Alex 75    schedule 14.11.2020    source источник
comment
Вы можете использовать синтаксис ячейки ref, но не так, вместо этого определите переменные a и b как ref Array.empty<byte>, а затем передайте их в качестве аргумента (без ключевого слова ref). Вы также можете просто сделать их mutable и передать адрес.   -  person s952163    schedule 14.11.2020


Ответы (1)


Вы правильно заметили, что упрощенный синтаксис F# для превращения параметров в возвращаемые кортежи работает только в очень ограниченных ситуациях — только когда у вас есть один параметр, и он последний. Другими словами, эта функция помогает с некоторыми распространенными шаблонами, но не полностью заменяет параметры.

Если вы хотите использовать параметр out в F#, вы можете либо передать ссылку на локальную изменяемую переменную, используя синтаксис &var, либо указать ячейку ссылки типа int ref в качестве аргумента. Ниже показаны два варианта использования стандартного метода TryParse:

// Using a local mutable variable
let mutable n = 0
Int32.TryParse("42", &n)
printfn "Got: %d" n

// Using a reference cell initialized to 0 
let n = ref 0
Int32.TryParse("42", n)
printfn "Got: %d" n.Value
person Tomas Petricek    schedule 15.11.2020