Parameter Action<T1, T2, T3> in which T3 can be optional

Sergio Romero picture Sergio Romero · Oct 7, 2011 · Viewed 15.6k times · Source

I have the following code:

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

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

Take notice of the optional param3 parameter.

Now for quite a few reasons I need to extract the code of the MyMethod method into its own class but I cannot extract ProtectedMethod with it because of all the classes that are inheriting from this one and I need to keep the changes small and isolated. So I figured I could have an Action<> delegate in the new class with the same signature as ProtectedMethod.

The problem is that if I declare the delegate like this:

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

The extracted code does not like it because it says the method is only being invoked with two parameters.

And if I declare the delegate like so:

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

When I send it as a parameter to the new class it does not like it either because the method is defined as having three parameters not two.

So far the only way I have thought of to solve this is to create an overloaded version of ProtectedMethod to eliminate the optional parameter.

Is this the only option or is there another way of doing it since now the preferred choice is to have optional parameters instead of overloaded methods?

Answer

SLaks picture SLaks · Oct 7, 2011

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.