【问题标题】:How to compose two lambdas of type "delegate" in c#如何在 C# 中组合两个“委托”类型的 lambda
【发布时间】:2015-06-17 07:30:27
【问题描述】:

假设我们已经定义了两个 Lambda。

Func<TInput, TOutput> a = …;
Func<TInput1, TInput2, TOutput> b = …;

现在让我们假设我们有一些代码不适用于泛型,并接收这些 Lambda 作为非进一步类型化的委托。

delegate da = a;
delegate db = b;

在该代码中,我们希望将两个 lambdas / delegates 组合成一个新的组合 lambda,例如(i1, i2) =&gt; b(a(i1), i2),但是 a 和 b 不可访问,只有 da 和 db 可访问。如何以优雅的方式做到这一点?

【问题讨论】:

  • 您的意思是Delegate,即System.Delegate?你为什么不直接DynamicInvoke
  • 我的意思是System.Delegate。我不想调用它,我想传递组合委托。
  • 我的意思是 (i1, i2) =&gt; b(a(i1), i2) 应该变成 (i1, i2) =&gt; db.DynamicInvoke(da.DynamicInvoke(i1), i2) 之类的东西,但我看到 Vera rind 在下面的回答中已经涵盖了这一点。当你有强类型时,比如a,你可以说a(i1)(与a.Invoke(i1)相同),因为签名在编译时是已知的。当您只有System.Delegate 时,您需要da.DynamicInvkoe(i1)。如果参数计数(和类型)正确,则无法在编译时检查。

标签: c# .net generics lambda


【解决方案1】:

这是你想要的吗?:

Func<int, int> a = p0 => p0 << 1;
Func<int, int, int> b = (p0, p1) => p0 + p1;

Delegate da = a;
Delegate db = b;

var inner = da.Method.GetParameters().Length < db.Method.GetParameters().Length ? da : db;
var outer = inner == da ? db : da;

Func<int, int, int> c = (i1, i2) => (int)outer.DynamicInvoke(inner.DynamicInvoke(i1), i2);

我更愿意创建一个表达式树来构建一个新的 lambda,它可以根据需要创建。也许需要更多的逻辑来确定应该将哪个参数传递给a,以及将a 的结果传递给b 的哪个参数。

这是你想要的方式吗?

【讨论】:

  • 我目前有一个带有表达式树的解决方案,但您的解决方案是我的问题的一个很好/更好的答案。谢谢,由于其他一些考虑,我会看看我将使用这两个解决方案中的哪一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
相关资源
最近更新 更多