【问题标题】:C# Delegates to methods with different optional parametersC# 委托给具有不同可选参数的方法
【发布时间】:2011-08-17 22:52:06
【问题描述】:

我知道我可以声明具有默认常量参数的委托,例如:

delegate void MyDelegate(int x, int y = 5);

然后用任何匹配签名的方法在任何地方调用它。

好的,我有很多这样声明的方法:

public Something FirstMethod(float val = 10, int skip = 0){ ... return sth; }
public Something SecondMethod(float val = 20, int skip = 0){ ... return sth; }
public Something ThirdMethod(float val = 5, int skip = 0){ ... return sth; }

...这个列表一直向上,无论如何,它们都有那个签名结构。这里的重点是,它们都有浮点参数,默认为不同的值。

然后,我想创建一个指向以下方法之一的委托:

delegate Something ProblematicDelegateType(<<WHAT WILL GO HERE>>);
ProblematicDelegateType myFunc;
if(someValue == someParameter){
    myFunc = FirstMethod;
}else if(...){
    myFunc = SecondMethod;
}else...
...
}

myFunc();
myFunc(skip:100);

我希望能够无参数或使用skip 参数调用myFunc。在这部分代码中,第一个参数val 没有被使用。 (它们在其他地方使用)。

什么将进入委托的参数列表?我想保留 该方法的默认 val 参数,无论它是什么。

【问题讨论】:

    标签: c# delegates optional-parameters


    【解决方案1】:

    如果我对您的理解正确,您的 myFunc 将完全省略 val 参数,始终使用您最终调用的任何方法的默认值,对吗?

    如果是这样,这应该可以满足您的要求:

    delegate Something ProblematicDelegateType(int skip = 0);
    ProblematicDelegateType myFunc;
    if (someValue == someParameter) {
        myFunc = skip => FirstMethod(skip: skip);
    } else if (...) {
        myFunc = skip => SecondMethod(skip: skip);
    } else ...
        ...
    }
    

    【讨论】:

    • 那一个确实有效,但有没有更好、更正式/模块化的方法呢?我正在寻找我不添加 skip =&gt; Method(skip:skip); 的东西,并且能够“以某种方式”直接调用 myFunc 指向的方法,而无需包装另一个 lambda。当然,如果可能的话:)
    • @can poyrazoğlu:这是不可能的。 FirstMethod、SecondMethod 等方法必须在某个地方显式调用,如果你想使用一些默认参数,因为只有在这些调用站点才会插入默认参数由编译器。所以唯一的办法就是把它们包裹起来
    • 好的,我将继续包装。但仍然不奇怪为什么它不能完成,因为签名是“硬编码”的,任何地方都没有泛型或类型转换,如果编译器知道参数的确切顺序和类型,逻辑上应该有一种方法进入那个。但无论如何我都会使用包装器。
    • 因为可选参数是在编译时确定的,而不是在运行时确定的。当你写 MyDelegate(1);编译器生成对 MyDelegate(1, 5); 的调用。它不知道运行时实际的委托是什么。
    【解决方案2】:

    使用 lambda 绑定所需的值。默认值实际上是重载,将您想要的值绑定到函数参数。由于您有各种 if 来分离函数,因此只需将委托传递给只接受整数的函数。

    换句话说,

    delegate Something ProblematicDelegateType(int skip = 0)
    
    //...
    
    ProblematicDelegateType myDelegate;
    if (someCondition)
      myDelegate = (_1) => FirstMethod(10, _1);
    else if (someOtherCondition)
      myDelegate = (_1) => SecondMethod(20, _1);
    

    等等..

    【讨论】:

    • 问题是我不想触及我正在调用的方法的另一个参数(第一个)。
    【解决方案3】:

    您要求委托具有根据其调用的方法而变化的可选参数的要求无法实现。可选参数是通过在编译时重写方法的调用点来实现的。如果委托指向的方法是在运行时确定的,它将在编译时写什么? Eric Lippert 在optional arguments 上的系列非常有启发性。

    但是,您也可以考虑使用反射来获取默认值。使用 MethodInfo.GetParameters() 获取参数信息,ParameterInfo.DefaultValue 获取默认值。

    【讨论】:

    • 我现在明白了.. 但我不想进行反思,我只想使用包装解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 2015-08-02
    • 2015-07-27
    • 1970-01-01
    • 2016-09-15
    相关资源
    最近更新 更多