tags:

views:

593

answers:

2

I tried the following code:

class Program: ProgParent
    {

        public int Max(params int[] op)
        {
            return 0;
        }

        public int Max(int i, params int[] op)
        {
            return 1;
        }

        public int Max(int i, int j, params int[] op)
        {
            return 2;
        }

        public static void Main(string[] args)
        {
            System.Console.WriteLine((new Program()).Max(5, 6, 7, 8));
            System.Console.ReadKey();
        }
    }

It executes, and uses the most specific function available. But the compiler gives no warning or error about this. Why?

A: 

Ignoring the build errors (which I'm putting down to typos) - what warning would you expect or want? It is finding a matching overload and using it...

Strictly speaking, I can call different overloads - by passing arrays, but yes, the usage isn't entirely clear.

Without the multiple overloads with params, this pattern is used quite heavily in things like string.Concat etc (which underpins + for strings under the bonnet).

Marc Gravell
WARNING: Your code is correct! :)
leppie
+3  A: 

The C# language spec says: "When performing overload resolution, a method with a parameter array may be applicable either in its normal form [i.e. passing an array] or its expanded form [i.e. passing a variable number of parameters]. The expanded form of a method is available only if the normal form of the method is not available and only if a method with the same signature as the expanded form is not already declared in the same type". In a (slightly simplified) nutshell: If overload resolution is ambiguous, the compiler chooses the non-params overload.

I guess the reasons for that decision (instead of making code like yours illegal) include:

  • If your method has the signature: void fn(params object[] p), you want to have some way to call the "normal form" (by passing an object[]). So the compiler has to handle ambiguous cases anyway.
  • Creating a temporary array is a lot more expensive than a method call, so you might want to create non-params overloads with 1,2,3 parameters that behave the same but are more efficient. (like e.g. String.Format)
Niki