Parameter Action<T1, T2, T3> in which T3 can be optional
Optional parameters are an attribute of a method or delegate parameter. When you call a signature (method or delegate) that has a known optional parameter at compile-time, the compiler will insert the optional parameter value at the callsite.
The runtime is not aware of optional parameters, so you can't make a delegate that inserts an optional parameter when it's called.
Instead, you need to declare a custom delegate type with an optional parameter:
public delegate void MyDelegate(IEnumerable<string> param1, string param2, int param3 = 1);
When calling this delegate, you will be able to omit the third parameter, regardless of the declaration of the method(s) it contains.
It would depend on how m_ProtectedMethod
would be consumed, but I found a compromise in my own situation, where I use one overload more than the other.
Simply define a simpler (having less generic parameters) Action<> variable, which calls the more complex supplied Action variable method. This can be accomplished either in (i) local scope on use; or (ii) object scope upon assignment of Action property or object construction.
Because there is no such thing as variable/property overloading, you need two different names, for the resulting two related Action variables.
EG i: Local Scope (probably not the most suitable for your scenario)
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: Object Scope
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
}
Note in both cases I designed the default setting value to be the more awkwardly named variable, having the 2 suffix, such that upon consumption the simpler overload has the more basic variable name.