gpt4 book ai didi

c# - 在 C# 中访问 F# 可区分联合类型的数据的最简单方法是什么?

转载 作者:IT王子 更新时间:2023-10-29 04:38:08 26 4
gpt4 key购买 nike

我正在尝试了解 C# 和 F# 协同工作的效果如何。我从 F# for Fun & Profit blog 中获取了一些代码它执行基本验证并返回可区分的联合类型:

type Result<'TSuccess,'TFailure> = 
| Success of 'TSuccess
| Failure of 'TFailure

type Request = {name:string; email:string}

let TestValidate input =
if input.name = "" then Failure "Name must not be blank"
else Success input

尝试在 C# 中使用它时;我能找到的访问成功和失败值的唯一方法(失败是一个字符串,成功又是请求)是使用大而讨厌的强制转换(需要大量输入,并且需要输入我期望的实际类型推断或在元数据中可用):

var req = new DannyTest.Request("Danny", "fsfs");
var res = FSharpLib.DannyTest.TestValidate(req);

if (res.IsSuccess)
{
Console.WriteLine("Success");
var result = ((DannyTest.Result<DannyTest.Request, string>.Success)res).Item;
// Result is the Request (as returned for Success)
Console.WriteLine(result.email);
Console.WriteLine(result.name);
}

if (res.IsFailure)
{
Console.WriteLine("Failure");
var result = ((DannyTest.Result<DannyTest.Request, string>.Failure)res).Item;
// Result is a string (as returned for Failure)
Console.WriteLine(result);
}

有更好的方法吗?即使我必须手动转换(可能会出现运行时错误),我也希望至少缩短对类型的访问( DannyTest.Result<DannyTest.Request, string>.Failure )。有没有更好的办法?

最佳答案

在不支持模式匹配的语言中,使用有区别的联合永远不会那么简单。但是,您的 Result<'TSuccess, 'TFailure> type 非常简单,应该有一些很好的方法可以从 C# 中使用它(如果类型更复杂,比如表达式树,那么我可能会建议使用访问者模式)。

其他人已经提到了一些选项 - 如何直接访问值以及如何定义 Match方法(如 Mauricio 的博客文章中所述)。我最喜欢的简单 DU 方法是定义 TryGetXyz遵循与 Int32.TryParse 相同风格的方法- 这也保证了 C# 开发人员将熟悉该模式。 F# 定义如下所示:

open System.Runtime.InteropServices

type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure

type Result<'TSuccess, 'TFailure> with
member x.TryGetSuccess([<Out>] success:byref<'TSuccess>) =
match x with
| Success value -> success <- value; true
| _ -> false
member x.TryGetFailure([<Out>] failure:byref<'TFailure>) =
match x with
| Failure value -> failure <- value; true
| _ -> false

这只是添加扩展 TryGetSuccessTryGetFailure返回 true当值通过 out 匹配区分联合案例的大小写和返回(所有)参数时参数。对于曾经使用过 TryParse 的人来说,C# 的使用非常简单:

  int succ;
string fail;

if (res.TryGetSuccess(out succ)) {
Console.WriteLine("Success: {0}", succ);
}
else if (res.TryGetFailure(out fail)) {
Console.WriteLine("Failuere: {0}", fail);
}

我认为熟悉这种模式是最重要的好处。当您使用 F# 并将其类型公开给 C# 开发人员时,您应该以最直接的方式公开它们(C# 用户不应以任何方式认为 F# 中定义的类型是非标准的)。

此外,这为您提供了合理的保证(当它被正确使用时)您将仅访问当 DU 匹配特定情况时实际可用的值。

关于c# - 在 C# 中访问 F# 可区分联合类型的数据的最简单方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17254855/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com