C# 如何在C语言中定义高阶函数的参数名#

C# 如何在C语言中定义高阶函数的参数名#,c#,functional-programming,higher-order-functions,C#,Functional Programming,Higher Order Functions,在C#中,可以创建高阶函数,即函数g以函数为参数。假设我想创建这样一个函数,它给定一个函数f,并返回另一个扩展其功能的函数。如何为返回的增强方法定义参数名?其动机是,我通常使用高阶方法,其中一些方法产生了新的方法。。由于没有附加参数名等,因此很难使用这些参数 举例说明如何在C#中分别定义g和f: 我定义了一个方法扩展,它可以扩展以T为参数并返回S的方法。 静态M类 { 公共静态函数扩展(函数扩展) { 返回(someT)=> { ... var结果=函数跟踪(someT); ... 返回结果;

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

举例说明如何在C#中分别定义
g
f

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

静态M类
{
公共静态函数扩展(函数扩展)
{
返回(someT)=>
{
...
var结果=函数跟踪(someT);
...
返回结果;
};
}
}

然后,我们可以在不更改方法的情况下在类上扩展方法。

类Calc2
{
公共函数Calc;
公共Calc2()
{
Calc=M.Extend(CalcPriv);
}
专用内部计算程序CPRIV(内部正枚举器)
{
if(positiveEnumber<0)抛出新异常(…);
控制台写入线(“计算”+i);
返回i++;
}
}

唉,参数名
positiveEnumber
不再可用,因为唯一可用的信息是
Func Calc
。也就是说,当我使用扩展方法时,键入
new Calc2().Calc(-1)
IDE没有提供任何帮助,说明我的参数是错误的

如果我们可以定义一个
委托
并将其转换为该委托,那就太好了,但是,这是不可能的


有什么建议吗?

这就是匿名代表的魅力所在;他们是匿名的。Func是一个方法的委托,该方法接受一个int并返回一个int。函数的实际作用以及参数的名称与此无关

唯一可行的方法是,如果Calc是命名的委托类型,定义的签名与CalcPriv相同。它仍然可以像写的那样工作,包括匿名扩展,但是您有一个命名的Calc参数

传递信息的另一种方法是使用
//
标记将信息传递给xml文档Calc,该标记描述Calc设计用于获取的参数


最后,您可以从
Func
派生来创建
TakesPositiveInteger
类。这有点过分了,但是如果您想谈论自文档化代码…

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

Func的定义如下:

public delegate TResult Func<in T, out TResult>(T arg)
public static T Extend(T functionToWrap)
{
}
不幸的是,没有好的泛型约束将输入类型限制为具有正确签名的委托(甚至只是委托)。但是如果没有这些约束,实现将变得非常丑陋,并且您将失去如此多的静态类型安全性,以至于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);
    }
公共静态转换T委托(委托d)
{
如果(!(类型(T).发布类别(类型(代表)))
抛出新ArgumentException(“T不是委托”);
如果(d==null)
抛出新ArgumentNullException();
MulticastDelegate md=d作为MulticastDelegate;
委托[]invList=null;
int invCount=1;
如果(md!=null)
invList=md.GetInvocationList();
if(invList!=null)
invCount=invList.Length;
如果(invCount==1)
{
return(T)(object)Delegate.CreateDelegate(typeof(T),d.Target,d.Method);
}
其他的
{
for(int i=0;i

顺便说一句,ConvertDelegate函数甚至可以用于在.net 4之前获取委托的协方差/逆变。通过将新构造的委托动态绑定到基础Func委托方法,可以使用命名参数强制转换为委托:

public delegate double CalcFunc(double value);

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

class Program
{
    private static double Calc(double input)
    {
        return 2*input;
    }

    [STAThread]
    static void Main()
    {
        Func<double, double> extended = M.Extend<double, double>(Calc);

        CalcFunc casted = (CalcFunc)Delegate.CreateDelegate(typeof(CalcFunc), extended.Target, extended.Method);
        Console.WriteLine(casted(2) + " == 4");
        Console.WriteLine("I didn't crash!");
        Console.ReadKey();
    }
}
公共委托双CalcFunc(双值);
静态M类
{
公共静态函数扩展(函数扩展)
{
返回(someT)=>functionToWrap(someT);
}
}
班级计划
{
专用静态双计算(双输入)
{
返回2*输入;
}
[状态线程]
静态void Main()
{
Func extended=M.Extend(计算);
CalcFunc casted=(CalcFunc)Delegate.CreateDelegate(typeof(CalcFunc),extended.Target,extended.Method);
控制台写入线(铸造(2)+“==4”);
控制台。WriteLine(“我没有崩溃!”);
Console.ReadKey();
}
}


警告一句:这不会对强制转换进行任何编译时检查。如果签名不完全匹配,则在运行时会出现绑定失败(除了.NET 4中对对冲的特殊支持)。

您需要知道参数名称的原因是什么?在您发布的代码中,您将在何处/如何使用它?这与创建继承M并重写Extend的类不同吗?以上只是一个示例,而不是问题。问题是能够使用高阶方法创建方法,这些方法记录了参数inputI,我的意思是,一般来说。我只是想知道这种构造的应用可能是什么,不能通过更传统的方法更直接地实现。这感觉就像你在寻找速记,或快速的
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);
    }
public delegate double CalcFunc(double value);

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

class Program
{
    private static double Calc(double input)
    {
        return 2*input;
    }

    [STAThread]
    static void Main()
    {
        Func<double, double> extended = M.Extend<double, double>(Calc);

        CalcFunc casted = (CalcFunc)Delegate.CreateDelegate(typeof(CalcFunc), extended.Target, extended.Method);
        Console.WriteLine(casted(2) + " == 4");
        Console.WriteLine("I didn't crash!");
        Console.ReadKey();
    }
}