我对F#几乎一无所知。我什至不知道语法,所以我无法举例子。
在注释线程中提到,F#可以声明可以采用多种可能类型的参数(例如字符串或整数)的函数。这类似于C#中的方法重载:
public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }
但是,在CIL中,您不能声明此形式的委托(delegate)。每个委托(delegate)必须有一个单独的,特定的参数类型列表。由于F#中的函数是一等公民,因此,您似乎应该可以传递此类函数,并且将其编译为CIL的唯一方法是使用委托(delegate)。
那么F#如何将其编译为CIL?
最佳答案
在编写C#时,需要一个可以采用多个不同参数集的函数,只需创建方法重载即可:
string f(int x)
{
return "int " + x;
}
string f(string x)
{
return "string " + x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
Console.WriteLine(func(12));
Console.WriteLine(func("12"));
}
callF
函数微不足道,但是我为call
函数编写的语法不起作用。在编写F#时,需要一个可以采用多个不同参数集的函数,然后创建一个可以包含所有不同参数集的有区别的并集,并创建一个采用该并集的单个函数:
type Either = Int of int
| String of string
let f = function Int x -> "int " + string x
| String x -> "string " + x
let callF =
printfn "%s" (f (Int 12))
printfn "%s" (f (String "12"))
let call func =
printfn "%s" (func (Int 12))
printfn "%s" (func (String "12"))
作为一个函数,
f
可以像其他任何值一样使用,因此在F#中,我们可以编写callF
和call f
,并且两者都做相同的事情。那么F#如何实现上面创建的
Either
类型?本质上是这样的:public abstract class Either
{
public class Int : Test.Either
{
internal readonly int item;
internal Int(int item);
public int Item { get; }
}
public class String : Test.Either
{
internal readonly string item;
internal String(string item);
public string Item { get; }
}
}
call
函数的签名为:public static void call(FSharpFunc<Either, string> f);
f
看起来像这样:public static string f(Either _arg1)
{
if (_arg1 is Either.Int)
return "int " + ((Either.Int)_arg1).Item;
return "string " + ((Either.String)_arg1).Item;
}
当然,您可以在C#中实现相同的
Either
类型(duh!),但这不是惯用的,这就是为什么它不是上一个问题的明显答案。