Wednesday, April 9, 2008

Dynamic number of parameters

Lastly I realized a very interesting feature of C#; the possibility to have a dynamic number of parameters for methods. This feature can easily be used in any method by specifying the "params" keyword and then providing an array of objects which holds the parameters. This technique allows you to create interesting methods and giving you the possibility to make your code shorter and better understandable.
First of all I'd like you to show an add method which accepts dynamic number of parameters.
public static int Add(params int[] numbersToAdd)
{
int sum = 0;
foreach (int number in numbersToAdd)
{
sum += number;
}
return sum;
}

It can be called in the following two ways:
int[] numbers = new int[4];
numbers[0] = 3;
numbers[1] = 8;
numbers[2] = 22;
numbers[3] = 2;
Console.WriteLine(Add(numbers));
/* OUTPUT
* 35
*/

or
Console.WriteLine(Add(3, 8, 22, 2));
/* OUTPUT
* 35
*/

Which version do you like more? I prefer the second one because I don't have to create an array of integers. Sure this method makes not really sense but it is only for demonstration purposes.
Another interesting method could be written which is the "Concat" method. It basically concatenates every object passed as parameter to a string and returns it:
public static string Concat(params object[] objects)
{
StringBuilder sb = new StringBuilder();
foreach (object obj in objects)
{
sb.Append(obj.ToString());
}
return sb.ToString();
}

The usage of this method would be the following:
Console.WriteLine("\n" + Concat("hello world ", 4, " ", true));
/* OUTPUT
* hello world 4 True
*/

Two other methods which could be interesting are the "Copy" and "CreateAndCopy" methods. The "CreateAndCopy" method takes an object as parameter, creates a new instance of the same type and copies the properties which are specified by their name in the parameters. In addition it is a generic so that no cast is necessary and it can be used with any object. Note that when calling this method the type has not necessarily be specified because C# defers the type from the object passed.
public static T CreateAndCopy<T>(T source, params string[] propertiesToCopy)
{
T target = (T)System.Activator.CreateInstance(typeof(T));
foreach (string propertyName in propertiesToCopy)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
property.SetValue(target, property.GetValue(source, null), null);
}
return target;
}

It can be used like this:
MyObject o1 = new MyObject();
o1.Text = "hallo";
o1.Number = 99;
o1.Boolean = true;

Console.WriteLine(o1.ToString());
/* OUTPUT
* MyObject:
* Text -> hallo
* Number -> 99
* Boolean -> True
*/

MyObject newObj = CreateAndCopy(o1, "Text", "Boolean");
Console.WriteLine(newObj.ToString());
/* OUTPUT
* MyObject:
* Text -> hallo
* Number -> 0
* Boolean -> True
*/

The "Copy" method does something similar but it accepts a destination object to which the values of the specified properties are copied to:
public static T Copy<T>(T source, T destination, params string[] propertiesToCopy)
{
foreach (string propertyName in propertiesToCopy)
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
property.SetValue(destination, property.GetValue(source, null), null);
}
return destination;
}

CONCLUSION:
The possibility to specify variable number of parameters may sometimes help to make the code easier to read and better understandable but in some circumstances it is better to create a class which holds all the required values and pass an instance of it to a method.

1 comment:

Juri Strumpflohner said...

I encountered this feature today morning when I was doing some experiments with C#. It's really a cool feature.
Ah, by the way, did you know that your blog does not allow anonymous users to post comments?? You have to be signed in.