Dienstag, 26. Juni 2012

Be careful with (optional) params[]

I just came across an issue with the C# params keyword. It allows you to pass an arbitrary number of arguments to function. Within the funciton the parameters are available as an array which might as well be empty.

The original signature looked like this:
public String GetFormattedMessage(int messageId, params object[] placeholderValues)
{...}

The method looked up the message with the given id in a database. The message might contain placeholder, in which the passed values must be inserted. Because a message can have any number of placeholders, they are passed as params-array (yes, the method handles the case of having to much / to less parameters as well :-))


Calls to the method looked like this:
// The operation {0} succeeded
var msg = GetFormattedMessage(4711, "load customers");
// Customer with first name {0} and last name {1} not found
var msg = GetFormattedMessage(4712, "John", "Smith");
// No service listenting on port {0}
var msg = GetFormattedMessage(4713, 8881);


The new requirement was to be able to hand in a default messagse in case the given message id could not be found, for example due to a missing database update.


So the new signature was:

public String GetFormattedMessage(int messageId, string defaultMessage, params object[] placeholderValues)
{...}

Here comes the problem with the overloaded method: the first two of the above calls immediatly started to call the new overload with the default message. In all cases, and these are the majority, where the first placeholder argument was a string, the second overload is called because the string placholder value is best to fit with the string defaultMessage parameter.

I could not find a nice solution for that. Here were the two options I considered:

  • Introduce a new type for the string defaultMessage parameter like so:
    public String GetFormattedMessage(int messageId, DefaultMessage defaultMessage, params object[] placeholderValues)
  • Do not overload but introduce a new method with a distinct name:
    public String GetFormattedMessageWithDefault(int messageId, string defaultMessage, params object[] placeholderValues)
I have choosen option two because it seemed more explicit to me. I am not happy with that but could not think of another solution - if anyone has thoughts about it, I would be glad to hear. If not, you may keep it in mind to avoid such a situation. At best avoid optinal parameters anyway.

Happy coding!

Keine Kommentare:

Kommentar veröffentlichen