gpt4 book ai didi

c# - F# 代码调用包含异常运行的 Func 参数的 c# 方法

转载 作者:太空狗 更新时间:2023-10-29 21:37:26 24 4
gpt4 key购买 nike

我们最近遇到了 F# 代码调用 C# 代码的问题。我已尽可能简单地简化了问题。 C#代码如下:

using System;

namespace CSharpLib
{
public abstract class InputMessageParent
{
public readonly Guid Id;

protected InputMessageParent(Guid id) { this.Id = id; }
}

public class Result { public string ResultString; }

public enum FunctionResult
{
None,
Good,
Bad
}

public class ConfigurationBuilder
{
public Result DoWork<TMessage>(
string param1,
Func<TMessage, FunctionResult> action)
where TMessage : InputMessageParent
{
return new Result() { ResultString = "Good" };
}
}
}

F#代码需要调用ConfigurationBuilders的DoWork函数。请注意,DoWork 函数采用两个参数,一个简单的字符串和一个 Func 作为第二个参数。 Func 接收一个必须从 InputMessageParent 继承的 TMessage 并返回一个简单的 Result 类型。 F#代码如下:

open System

type InputMessageConcreteTypeA =
inherit CSharpLib.InputMessageParent
val Property1:string
new (id, property1Value) =
{
inherit CSharpLib.InputMessageParent(id)
Property1 = property1Value
}

[<EntryPoint>]
let main argv =

let actionImpl (input:InputMessageConcreteTypeA) =
CSharpLib.FunctionResult.Good

let builder = new CSharpLib.ConfigurationBuilder()
builder.DoWork("param1", actionImpl) |> ignore

0

此代码无法编译。 actionImpl 类型是 InputMessageConcreteTypeA -> CSharpLib.FunctionResult,这正是 DoWork 期望的第二个参数的类型,但它却给我以下错误:This expression was expected to have type 'Func<'a,CSharpLib.FunctionResult>' but here has type 'b -> CSharpLib.FunctionResult'

有趣的是,如果我将代码更改为以下代码,它会编译:

[<EntryPoint>]
let main argv =

let actionImpl (input:InputMessageConcreteTypeA) =
CSharpLib.FunctionResult.Good

let builder = new CSharpLib.ConfigurationBuilder()
builder.DoWork("param1", fun input -> actionImpl(input)) |> ignore

0

为什么代码会针对与 actionImpl 完全相同的类型定义的内联匿名函数进行编译,但如果我直接传递 actionImpl 则不会编译?内联匿名函数看起来毫无意义,但却是我们目前唯一的解决方案。有没有更好的办法?

最佳答案

F# 函数类型 'a -> 'b 不是,其实和C#类型一样Func<a,b> .

它们不同的原因尚无定论,但结果是您不能随心所欲地将一种类型当作另一种类型。类型不匹配。这就是编译器告诉您的内容:应具有类型 Func<...>,但此处具有类型 'b -> ...

但是,对于 lambda 表达式,编译器会抛出异常。通常,lambda 表达式 fun x -> e将具有类型 'a -> 'b (其中 x:'ae:'b ),但在从上下文中已知预期类型为 Func<_,_> 的情况下编译器将强制并将 lambda 表达式编译为 Func .

此异常(exception)是为了简化与大量使用 lambda 表达式的 .NET 库(例如 LINQ)的互操作。但此异常(exception)不适用于按名称引用命名函数。它可能应该适用,但事实并非如此。

如果您不想使用无意义的 lambda 表达式,唯一的其他方法是显式创建类型为 Func<_,_> 的对象。通过调用它的构造函数并将函数传递给它,然后将该对象传递给 DoWork :

builder.DoWork("param1", Func<_,_> actionImpl)

关于c# - F# 代码调用包含异常运行的 Func 参数的 c# 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57674161/

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