2013-01-25 39 views
1

我在F#做了一個功能如何解決這個關於out和tuple形式的互操作問題?

let tryParseArray tryParse (separator:char) (line: string) = 
    // inside the function I use the tuple form of tryParse 

它工作正常,如果我把它以這樣一種方式:tryParseArray Int32.TryParse ',' "2,3,2,3,2"

現在我想這個功能是在C#中可以作爲很好,所以我這樣做:

static member TryParseArray (line, tryParse, separator) = 
    line |> tryParseArray tryParse separator 

然後我意識到TryParseArray其實需要tryParse參數爲FSharpFunc,這是不友善的C#好,所以我想這:

static member TryParseArray (line, [<Out>] tryParse: (string * byref<'a> -> bool), separator) = 
    line |> tryParseArray tryParse separator 

但現在tryParseArray不接受tryParse作爲有效參數(錯誤類型)

我應該怎麼辦?

我想在C#中我可以打電話給TryParseArray("2,3,2,3,2", Int32.TryParse, ',')以及

回答

5

您可以使用自定義的委託類型公開此功能爲C#:

EDITED

// F# 
module Lib 

let tryParseArray parser (line : string) (sep : char) = 
    // don't know your exact implementation so again just guessing... 
    line.Split sep 
    |> Array.choose (fun el -> 
     match parser el with 
     | true, el -> Some el 
     | false, _ -> None 
     ) 

open System.Runtime.InteropServices 
type TryParse<'R> = delegate of str : string * [<Out>] res : byref<'R> -> bool 

type T = 
    static member TryParse(line : string, tryParse : TryParse<'R>, separator : char) : 'R[] = 
     tryParseArray tryParse.Invoke line separator 


//C# 
var r = Lib.T.TryParse<int>("1,2,3", int.TryParse, ','); 

注:在C#側您需要明確指定TryParse的類型參數(Why don't anonymous delegates/lambdas infer types on out/ref parameters?

+1

+1顯示如何在委託參數中放置'[]'屬性。 – Daniel

+0

thx,基本上解決了我的問題。儘管如此,在F#中,我不能'讓r = Lib.T.TryParse (「1,2,3」,int.TryParse,',')',任何解決方法? (我知道我可以調用'tryParseArray') – colinfang

+0

Lib.T.TryParse(「1,2,3」,(fun s r - > System.Int32.TryParse(s,r)),',')? – desco

0

d ESCO的解決方案是好的,但如果你想避免byref你可以做這樣的事情:

type TryParse<'R> = delegate of string -> bool * 'R 

module Util = 
    [<CompiledName("TryParseArray")>] 
    let tryParseArray (tryParse: TryParse<_>) (separator:char) (line: string) = ... 

可以從F#這樣調用:

let res = Util.tryParseArray (TryParse(Int32.TryParse)) ',' "1,2,3" 

,並與下面的包裝方法:

static class TryParse { 
    public static Tuple<bool, int> Int32(string s) { 
     int i; 
     var b = System.Int32.TryParse(s, out i); 
     return Tuple.Create(b, i); 
    } 
} 

這樣,從C#:

var res = Util.TryParseArray(TryParse.Int32, ',', "1,2,3");