使用 UWP、.NET Core v2.0.3 和 C# v7.3 从 C# 方法调用 F# discriminated union?
Calling F# discriminated union from C# method using UWP, .NET Core v2.0.3 and C# v7.3?
我们应用的 UWP 库限制我们使用 .NET Core 2.0.3。我们的代码使用 C# v7.3,我们一直在试验 F#。
在我们的 .NET Core v2.0.3 和 C# v7.3 版本中,如何处理从 F# 返回的可区分联合?
一些建议是use a C# switch to handle an F# function returned discriminated union。
将以下 F# 和 C# 代码放入带有 F# 和 C# 项目的测试控制台应用中...
F#
type LogLevels =
| Error
| Warning
| Info
C#调用F#
private static void Main()
{
LogLevels level = LogLevels.Info;
switch (level.Tag)
{
case LogLevels.Tags.Error:
Console.WriteLine("error");
break;
case LogLevels.Tags.Warning:
Console.WriteLine("warning");
break;
case LogLevels.Tags.Info:
Console.WriteLine("info"); //prints info
break;
default:
throw new ArgumentOutOfRangeException();
}
}
….就像@madreflection 说的那样工作正常。
但是如果返回 System.Threading.Tasks.Task
而不是 int
,我会得到编译器错误 CS8370: Feature ‘type pattern’ is not available in C# 7.3. Please use language version 9.0 or greater.
在我的尝试中 我使用在 C# 中工作并且应该在 F# 中工作的 API 从 Azure 密钥保管库检索密钥。
F# 代码 是……
type public SENSITIVE_ITEM =
| SECRET_C of KeyVaultSecret
| KEY_C of KeyVaultKey
type public TASK_SENSITIVE_ITEM =
| TASK_GET_SECRET_C of Task<Azure.Response<KeyVaultSecret>>
| TASK_GET_KEY_C of Task<Azure.Response<KeyVaultKey>>
let GetAsync ( item : SENSITIVE_ITEM) (vaultURI : Uri) : TASK_SENSITIVE_ITEM =
match item with
| SECRET_C(secret) -> VClient_Secret(vaultURI).GetSecretAsync(secret.Name) |> TASK_GET_SECRET_C
| KEY_C(key) -> VClient_Key(vaultURI).GetKeyAsync(key.Name) |> TASK_GET_KEY_C
...我的 GetAsync
单元测试中的 C# 代码 是……
public void GetAsync_Key()
{
KeyVaultKey key = new KeyVaultKey(keyName);
var fs_sensitive_item_key = KeyVaultAccess.SENSITIVE_ITEM.NewKEY_C(key);
var task = KeyVaultAccess.GetAsync(fs_sensitive_item_key, vaultUri);
switch (task)
{
case KeyVaultAccess.TASK_SENSITIVE_ITEM.TASK_GET_KEY_C:
Console.WriteLine("got a key task.");
break;
case KeyVaultAccess.TASK_SENSITIVE_ITEM.TASK_GET_SECRET_C:
Console.WriteLine("got a secret task.");
break;
default:
break;
}
Assert.True(false);
}
两个C#case
匹配表达式报错。这可能是因为 C# 7.0.3 不支持开关中的模式匹配。 (如错误所述)。
这是一个问题,因为 UWP is not supported in .NET 5.0 使用 C# v9.0 或更高版本需要它。
那么,在我们的 .NET Core v2.0.3 和 C# v7.3 的有限版本中,如何处理从 F# 返回的有区别的联合?
F# 编译器为可区分联合生成所谓的“扩充”。
在 C# 中使用 LogLevel
类型时,您可以 access/check 使用生成的 Is[caseName]
属性针对特定情况。
具有大小写值的可区分联合。
根据 madreflection 的建议,我想通了...
使用 *.Tags.*
嵌套的 class 成员如下...
switch (task.Tag)
{
case KeyVaultAccess.TASK_SENSITIVE_ITEM.Tags.TASK_GET_KEY_C:
Console.WriteLine("got a key task.");
break;
case KeyVaultAccess.TASK_SENSITIVE_ITEM.Tags.TASK_GET_SECRET_C:
Console.WriteLine("got a secret task.");
break;
default:
Console.WriteLine("default.");
break;
}
这有效。
我们应用的 UWP 库限制我们使用 .NET Core 2.0.3。我们的代码使用 C# v7.3,我们一直在试验 F#。
在我们的 .NET Core v2.0.3 和 C# v7.3 版本中,如何处理从 F# 返回的可区分联合?
一些建议是use a C# switch to handle an F# function returned discriminated union。
将以下 F# 和 C# 代码放入带有 F# 和 C# 项目的测试控制台应用中...
F#
type LogLevels =
| Error
| Warning
| Info
C#调用F#
private static void Main()
{
LogLevels level = LogLevels.Info;
switch (level.Tag)
{
case LogLevels.Tags.Error:
Console.WriteLine("error");
break;
case LogLevels.Tags.Warning:
Console.WriteLine("warning");
break;
case LogLevels.Tags.Info:
Console.WriteLine("info"); //prints info
break;
default:
throw new ArgumentOutOfRangeException();
}
}
….就像@madreflection 说的那样工作正常。
但是如果返回 System.Threading.Tasks.Task
而不是 int
,我会得到编译器错误 CS8370: Feature ‘type pattern’ is not available in C# 7.3. Please use language version 9.0 or greater.
在我的尝试中 我使用在 C# 中工作并且应该在 F# 中工作的 API 从 Azure 密钥保管库检索密钥。
F# 代码 是……
type public SENSITIVE_ITEM =
| SECRET_C of KeyVaultSecret
| KEY_C of KeyVaultKey
type public TASK_SENSITIVE_ITEM =
| TASK_GET_SECRET_C of Task<Azure.Response<KeyVaultSecret>>
| TASK_GET_KEY_C of Task<Azure.Response<KeyVaultKey>>
let GetAsync ( item : SENSITIVE_ITEM) (vaultURI : Uri) : TASK_SENSITIVE_ITEM =
match item with
| SECRET_C(secret) -> VClient_Secret(vaultURI).GetSecretAsync(secret.Name) |> TASK_GET_SECRET_C
| KEY_C(key) -> VClient_Key(vaultURI).GetKeyAsync(key.Name) |> TASK_GET_KEY_C
...我的 GetAsync
单元测试中的 C# 代码 是……
public void GetAsync_Key()
{
KeyVaultKey key = new KeyVaultKey(keyName);
var fs_sensitive_item_key = KeyVaultAccess.SENSITIVE_ITEM.NewKEY_C(key);
var task = KeyVaultAccess.GetAsync(fs_sensitive_item_key, vaultUri);
switch (task)
{
case KeyVaultAccess.TASK_SENSITIVE_ITEM.TASK_GET_KEY_C:
Console.WriteLine("got a key task.");
break;
case KeyVaultAccess.TASK_SENSITIVE_ITEM.TASK_GET_SECRET_C:
Console.WriteLine("got a secret task.");
break;
default:
break;
}
Assert.True(false);
}
两个C#case
匹配表达式报错。这可能是因为 C# 7.0.3 不支持开关中的模式匹配。 (如错误所述)。
这是一个问题,因为 UWP is not supported in .NET 5.0 使用 C# v9.0 或更高版本需要它。
那么,在我们的 .NET Core v2.0.3 和 C# v7.3 的有限版本中,如何处理从 F# 返回的有区别的联合?
F# 编译器为可区分联合生成所谓的“扩充”。
在 C# 中使用 LogLevel
类型时,您可以 access/check 使用生成的 Is[caseName]
属性针对特定情况。
具有大小写值的可区分联合。
根据 madreflection 的建议,我想通了...
使用 *.Tags.*
嵌套的 class 成员如下...
switch (task.Tag)
{
case KeyVaultAccess.TASK_SENSITIVE_ITEM.Tags.TASK_GET_KEY_C:
Console.WriteLine("got a key task.");
break;
case KeyVaultAccess.TASK_SENSITIVE_ITEM.Tags.TASK_GET_SECRET_C:
Console.WriteLine("got a secret task.");
break;
default:
Console.WriteLine("default.");
break;
}
这有效。