c# - 如何在 C# 中为高阶函数定义参数名称

标签 c# functional-programming higher-order-functions

在 C# 中,可以创建高阶函数,即。函数 g以函数作为参数。假设我想创建一个给定函数 f 的函数并返回另一个扩展其功能的函数。 我如何为返回的增强方法定义参数名称? 这样做的动机是,我通常使用高阶方法,其中一些会产生新方法......而这些方法可能很难使用因为没有附加参数名称等。

说明如何 g 的示例和 f分别可以在 C# 中定义:

我定义了一个 Extend 方法,它可以扩展采用 T 的方法。作为参数并返回 S .

static class M
{
    public static Func< T, S> Extend(Func< T, S> functionToWrap)
    {
      return (someT) =>
      {
        ...
        var result = functionToWrap(someT);
        ...
        return result;
      };
    }
}

然后我们可以在我们的类上扩展一个方法而不改变方法。

class Calc2
{
    public Func< int, int> Calc;
    public Calc2()
    {
      Calc = M.Extend< int, int>(CalcPriv);
    }
    private int CalcPriv(int positiveNumber)
    {
      if(positiveNumber < 0) throw new Exception(...);
      Console.WriteLine("calc " + i);
      return i++;
    }
}

唉,参数名positiveNumber不再可用,因为唯一可用的信息是 Func<int, int> Calc .那是当我通过键入 new Calc2().Calc(-1) 使用扩展方法时我没有从 IDE 那里得到任何帮助,事实上我的论点是错误的。

如果我们能定义一个 delegate 就好了并将其转换到这个,但是,这是不可能的。

有什么建议吗?

最佳答案

如果您只想要一个带有命名参数的固定委托(delegate)类型,那么您可以定义自己的委托(delegate)类型:

Func 就是这样定义的:

public delegate TResult Func<in T, out TResult>(T arg)

因此您可以使用您想要的参数名称定义您自己的委托(delegate)类型。

但在您的示例中,您希望保留传入的委托(delegate)类型,因此这在这里不起作用。理论上你可以这样定义你的函数:

public static T Extend(T functionToWrap)
{
}

不幸的是,没有好的通用约束将输入类型限制为具有正确签名的委托(delegate)(或者甚至只是委托(delegate))。但是如果没有这些限制,实现会变得非常丑陋,并且您会失去如此多的静态类型安全性,IMO 认为这是不值得的。

一种解决方法是使用:

new MyFunc(Extend(f))

其中 MyFunc 定义了您想要的参数名称。

或者您可以执行以下操作:

public static T ConvertDelegate<T>(Delegate d)
{
    if (!(typeof(T).IsSubclassOf(typeof(Delegate))))
        throw new ArgumentException("T is no Delegate");
    if (d == null)
        throw new ArgumentNullException();
    MulticastDelegate md = d as MulticastDelegate;
    Delegate[] invList = null;
    int invCount = 1;
    if (md != null)
        invList = md.GetInvocationList();
    if (invList != null)
        invCount = invList.Length;
    if (invCount == 1)
    {
        return (T)(object)Delegate.CreateDelegate(typeof(T), d.Target, d.Method);
    }
    else
    {
        for (int i = 0; i < invList.Length; i++)
        {
            invList[i] = (Delegate)(object)ConvertDelegate<T>(invList[i]);
            }
            return (T)(object)MulticastDelegate.Combine(invList);
        }
    }

public static TDelegate Extend<TDelegate,TArg,TResult>(Func<TArg,TResult> functionToWrap)
where TDelegate:class
    {       
        Func<TArg,TResult> wrappedFunc= DoTheWrapping(functionToWrap);
        return ConvertDelegate<TDelegate>(wrappedFunc);
    }

顺便说一句,即使在 .net 4 之前,ConvertDelegate 函数也可用于获取委托(delegate)的 Co/Contravariance。

关于c# - 如何在 C# 中为高阶函数定义参数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4047158/

相关文章:

function - 为什么不支持高阶函数中的注释?

c# - 需要在.NET应用程序中播放mp3文件的帮助?

c# - C# 中的自动完成 block

python - 使用 str.startswith 的高阶函数

haskell - 当我在 Haskell 中用 + 组合 * 时会发生什么?

functional-programming - 函数级语言和函数级语言之间的正式区别是什么?

scala - 使用集合作为函数

c# - 我可以从一个线程使用 System.Threading.Timer 启动多少个线程(计时器)?

c# - WCF:如何在端口 80 上配置 net.tcp 流量

functional-programming - 函数式编程 : how far should immutability go?