使用C#中的嵌入空格("XXX YY``)调用F#勾选的函数名称

kim*_*msk 10 c# f# c#-to-f#

在F#中,我们可以创建一个这样的函数:

let ``add x and y`` x y = x + y
Run Code Online (Sandbox Code Playgroud)

我可以像这样称呼它:

``add x and y`` 1 2
Run Code Online (Sandbox Code Playgroud)

有没有办法从C#端调用上面的函数?我甚至无法在对象浏览器中看到它.

Gen*_*ski 17

您可以使用CompiledName属性将任何有效的 F#函数名称公开为C#作为任何C#有效函数名称:

namespace Library1
module Test = 
    [<CompiledName("Whatever")>]
    let ``add a and b`` x y = x + y
Run Code Online (Sandbox Code Playgroud)

然后在C#中:

 using Library1;
 ...............
 System.Console.WriteLine(Test.Whatever(2,2));
Run Code Online (Sandbox Code Playgroud)

后续2016年3月5日从评论NICKL,至少适用于F#3.1:

从功能转移到成员会带来一些"ifs and buts".

首先,如果从pure使用CompiledName属性,则不会编译属性.仅仅编译需要在一个内部使用.membernamespacemodule

当在F#记录的module装饰方法中使用时 member,无论两个刻度之间的内容如何看起来都能正常工作.但是,当装饰F#记录的属性时 member,CompiledName只有当双刻度之间的内容类似于某些合法值名称时,才能看到交叉汇编:

module M

type MyRecord =
    { myField: string }
    [<CompiledName "Whatever">]
    member x.``Blah Blah blah``() = x.myField
    [<CompiledName "Another">]
    member x.``ABC`` = x.myField
Run Code Online (Sandbox Code Playgroud)

然后从C#下面的工作正常:

var recInC = new M.MyRecord("Testing...");
Console.WriteLine(recInC.Whatever());
Console.WriteLine(recInC.Another);
Run Code Online (Sandbox Code Playgroud)

这种不一致促使潜在的问题.


Jef*_*ado 6

反思可能是唯一的方法,但使用它并不一定难看.只需将它全部包装在一个类中即可进行反射.

public static class MyModuleWrapper
{
    // it would be easier to create a delegate once and reuse it
    private static Lazy<Func<int, int, int>> addXAndY = new Lazy<Func<int, int, int>>(() =>
        (Func<int, int, int>)Delegate.CreateDelegate(typeof(Func<int, int, int>), typeof(MyModule).GetMethod("add x and y"))
    );
    public static int AddXAndY(int x, int y)
    {
        return addXAndY.Value(x, y);
    }

    // pass other methods through.
    public static int OtherMethod(int x, int y)
    {
        return MyModule.OtherMethod(x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像平常一样使用它.

var sum = MyModuleWrapper.AddXAndY(1, 2);
var otherValue = MyModuleWrapper.OtherMethod(1, 2); // use the wrapper instead
Run Code Online (Sandbox Code Playgroud)

我不确定需要改变什么或者如果涉及多态类型,但希望你能得到这个想法并且可以应用必要的更改.