参数动作 其中T3可以是可选的

问题描述 投票:29回答:3

我有以下代码:

public static MyMethod()  
{ 
   ...Do something  
   ProtectedMethod(param1, param2);  
   ...Do something  
}  

protected static void ProtectedMethod(IEnumerable<string> param1, string param2, int param3 = 1)  
{  
   ... Do something  
}

注意可选的param3参数。

现在由于很多原因,我需要将MyMethod方法的代码提取到它自己的类中,但我不能用它提取ProtectedMethod,因为所有继承自这个的类都需要保持变化小而孤立。所以我想我可以在新类中使用与ProtectedMethod相同签名的Action <>委托。

问题是如果我像这样声明委托:

protected readonly Action<IEnumerable<string>, string, int> m_ProtectedMethod;

提取的代码不喜欢它,因为它表示只使用两个参数调用该方法。

如果我像这样声明代表:

protected readonly Action<IEnumerable<string>, string> m_ProtectedMethod;

当我将它作为参数发送到新类时,它不喜欢它,因为该方法被定义为具有三个参数而不是两个参数。

到目前为止,我想到解决这个问题的唯一方法是创建一个重载版本的Protected Method来消除可选参数。

这是唯一的选择还是有另一种方法,因为现在首选的选择是使用可选参数而不是重载方法?

c# oop delegates optional-parameters
3个回答
29
投票

可选参数是方法或委托参数的属性。在编译时调用具有已知可选参数的签名(方法或委托)时,编译器将在调用点处插入可选参数值。

运行时不知道可选参数,因此您无法在调用时插入可选参数。

相反,您需要使用可选参数声明自定义委托类型:

public delegate void MyDelegate(IEnumerable<string> param1, string param2, int param3 = 1);

调用此委托时,无论其包含的方法声明如何,您都可以省略第三个参数。


1
投票

这将取决于m_ProtectedMethod将如何消耗,但我发现在我自己的情况下妥协,我使用一个重载比另一个更多。

只需定义一个更简单(具有更少通用参数)的Action <>变量,它调用更复杂的Action变量方法。这可以在(i)使用的当地范围内完成;或(ii)转让行动财产或物体构造的对象范围。

因为没有变量/属性重载这样的东西,所以需要两个不同的名称,用于生成两个相关的Action变量。

EG i:本地范围(可能不是最适合您的场景)

public MyMethod(Action<IEnumerable<string>, string, int> m_ProtectedMethod2)  
{ 
   Action<IEnumerable<string>, string> m_ProtectedMethod = (p1,p2) => {
      m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
   }

   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}  

EG ii:对象范围

private Action<IEnumerable<string>, string, int> m_ProtectedMethod2 = null;
private Action<IEnumerable<string>, string> m_ProtectedMethod = null;
protected Action<IEnumerable<string>, string, int> ProtectedMethod
{
   get { return m_ProtectedMethod2; }
   set {
      m_ProtectedMethod2 = value;
      m_ProtectedMethod = (p1,p2) => {
         m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter
      }
   }
}

public MyMethod()
{
   ...Do something  
   m_ProtectedMethod(param1, param2);  
   ...Do something  
   ...If something  
      m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly
   ...Do something  
}

请注意,在这两种情况下,我将默认设置值设计为更加笨拙的命名变量,具有2个后缀,这样在使用时,更简单的重载具有更基本的变量名称。


-1
投票

希望通过我发现的更优雅的重载实现与(委托导向的)策略模式相结合来帮助其他人。

public class OverloadExample {
    private Action<int, bool> _implementation;

    public OverloadExample() {
        _implementation = defaultImplementation;
    }

    public OverloadExample(Action<int, bool> implementation) {
        _implementation = implementation;
    }

    protected void defaultImplementation(int aInt, bool aBool) {
        //
    }

    public void Implementation(int someInt, bool someBool = true) {
        _implementation(someInt, someBool);
    }
}

用法:

new OverloadExample().Implementation(9001);
new OverloadExample().Implementation(9001, false);
© www.soinside.com 2019 - 2024. All rights reserved.