C# 模式匹配C代码中的F#类型
假设有一个C# 模式匹配C代码中的F#类型,c#,f#,interop,C#,F#,Interop,假设有一个F#定义: type one=| a的左边| b的右边 设f(i:int):或者= 如果i>0 然后我离开了 否则“什么都没有” 函数f用于C代码: var a=Library.f(5); 如何为数据构造函数匹配结果值a?比如: /* (如果a是左x) 用x做点什么 (如果a正确,则为y) 和我做点什么 */ 使用F#区别于C#的联合有点不雅观,因为它们是如何编译的 我认为最好的方法是定义一些成员(在F#端),以简化使用C#中的类型。有多种选择,但我更喜欢的是定义TryLeft和T
F#
定义:
type one=| a的左边| b的右边
设f(i:int):或者=
如果i>0
然后我离开了
否则“什么都没有”
函数f
用于C
代码:
var a=Library.f(5);
如何为数据构造函数匹配结果值a
?比如:
/*
(如果a是左x)
用x做点什么
(如果a正确,则为y)
和我做点什么
*/
使用F#区别于C#的联合有点不雅观,因为它们是如何编译的
我认为最好的方法是定义一些成员(在F#端),以简化使用C#中的类型。有多种选择,但我更喜欢的是定义TryLeft
和TryRight
方法,它们的行为类似于Int32.TryParse
(因此,使用F#API的C#开发人员应该熟悉它们):
open System.Runtime.InteropServices
类型=
|a的左边
|b的权利
成员x.TryLeft([]a:byref)=
将x与右v匹配->b为假
然后您可以使用C#中的类型,如下所示:
int a;
string s;
if (v.TryLeft(out a)) Console.WriteLine("Number: {0}", a);
else if (v.TryRight(out s)) Console.WriteLine("String: {0}", s);
这样做会失去一些F#安全性,但这在没有模式匹配的语言中是意料之中的。但好的是,熟悉.NET的任何人都应该能够使用在F#中实现的API
另一种选择是定义成员Match
,该成员接受Func
委托,并使用左/右大小写携带的值调用右委托。从功能的角度来看,这有点好,但对于C#调用者来说可能不太明显。从以下方面:
8.5.4从其他CLI语言使用的联合类型的编译形式
已编译的联合类型U具有:
此解决方案很方便,因为它还通过为元组中的每个项创建新属性来处理元组DU情况。我将定义一个
匹配成员,在每个场景中执行代理。在F#中,您可以这样做(但如果需要,您可以在C#扩展方法中做一些等效的事情):
type one=| a的左边| b的右边
具有
请记住,该解决方案有一些限制。比如,您不能执行类似a.Match的操作(ifLeft:x=>x+1,ifRight:=>returnnull)代码>
class Program
{
static void Main(string[] args)
{
PrintToConsole("5");
PrintToConsole("test");
}
static void PrintToConsole(string value)
{
var result = test.getResult(value);
if (result.IsIntValue) Console.WriteLine("Is Int: " + ((test.DUForCSharp.IntValue)result).Item);
else Console.WriteLine("Is Not Int: " + ((test.DUForCSharp.StringValue)result).Item);
}
}
namespace Library1
module test =
open System
type DUForCSharp =
| IntValue of int
| StringValue of string
let getResult x =
match Int32.TryParse x with
| true, value -> IntValue(value)
| _ -> StringValue(x)