Alex Rivera | Logout

C# variable length args, which is better and why: __arglist, params array or Dictionary<T,K>?

Asked 2009-05-26T13:09:42.063
12

I recently read the following overflow post: Hidden Features of C#

One of the features pointed out was the arglist. Why would one choose this or the alternatives as a means of using a variable length argument list to a method? Also, note that I would probably not use this kind of construct in my code unless a corner case warranted doing so. This is more of a question of semantics than whether it is even practical or prudent to even use variable length arguments. So does anyone know which is better and why?

 [Test]
 public void CanHandleVariableLengthArgs()
 {
     TakeVariableLengthArgs(__arglist(new StringBuilder(), 12));

     object[] arr = { new StringBuilder() };
     TakeVariableLengthArgs2(arr);

     TakeVariableLengthArgs3(
         new Dictionary<string, object> 
         { { "key", new StringBuilder() } });
 }

 public void TakeVariableLengthArgs(__arglist)
 {
      var args = new ArgIterator(__arglist);

      var a = (StringBuilder)TypedReference.ToObject(args.GetNextArg());
      a.Append(1);
 }

 public void TakeVariableLengthArgs2(params object[] args)
 {
      var a = (StringBuilder)args[0];
      a.Append(1);
 }

 public void TakeVariableLengthArgs3(Dictionary<string, object> args)
 {
      var a = (StringBuilder)args["StringBuilder"];
      a.Append(1);
 }
Edit
Report

2 Answers

3

It depends on the case. I've used params in cases where I have a variable number of arguments and it significantly adds to the readability of the calling code.

For example, I have a class that represents a TIFF document and allows access to a collection of pages which can be reordered and interspersed with other TIFF documents. Since one of the most common tasks our customers want is the ability to easily combine multiple TIFF documents into a single, we also provide the following two utility methods:

public static void Combine(Stream output, params Stream[] sources) { /* ... */ }
public static void Combine(Stream output, params string[] sourceFiles) { /* ... */ }

which in usage make the client code feel really nice:

using (FileStream output = new FileStream(outputPath, FileMode.Create)) {
    TiffDocument.Combine(output, tpsCoverSheetPath, mainDocumentPath, tpsTrailerPath);
}
answered 2009-05-26T14:03:04.967
3

C# 4 will have a better mechanism for this; named and optional arguments:

static void Main(string[] args)
{
    // The method can be called in the normal way, by using positional arguments.
    Console.WriteLine(CalculateBMI(123, 64));

    // Named arguments can be supplied for the parameters in either order.
    Console.WriteLine(CalculateBMI(weight: 123, height: 64));
    Console.WriteLine(CalculateBMI(height: 64, weight: 123));

    // Positional arguments cannot follow named arguments.
    // The following statement causes a compiler error.
    //Console.WriteLine(CalculateBMI(weight: 123, 64));

    // Named arguments can follow positional arguments.
    Console.WriteLine(CalculateBMI(123, height: 64));
}

static int CalculateBMI(int weight, int height)
{
    return (weight * 703) / (height * height);
}
answered 2009-05-26T14:13:38.410

Your Answer