tags:

views:

346

answers:

6

Consider the following class

public class PlanetKrypton
 {
  public static void CallSuperManforHelp(string helpMessage, params object[] kryptonParams)
  {
   Console.WriteLine(String.Format(helpMessage,kryptonParams));
  }

  public static void CallSuperManforHelp(string helpMessage ,string sender,string senderZipCode)
  {
   Console.WriteLine("{0} from {1}. I am {2}", helpMessage, sender, senderZipCode);
  }
 }

 public class ConsoleMan
 {
  public static void Main(string[] args)
  {
   string helpMessage = "I have a flat tire";
   string sender = "Jerry";
   int wrongZipType = 12345;


   PlanetKrypton.CallSuperManforHelp(helpMessage, sender, wrongZipType);
   PlanetKrypton.CallSuperManforHelp(helpMessage);
  }
 }

Now, if I have a more strongly typed method signature in the first method, I would have gotten a compile time error for both these method calls.

Are there any "best practices" for using params in method signature ?

Edit:Am making this a community wiki

+2  A: 

Well, the obvious thing is that compile time errors are better than runtime errors. However, a flexible, usable API sometimes has to take precedence. I'd say in general you should only use arrays of Object, which lack compile time type safety and are sometimes inefficient, if you're sure there's no more static way to accomplish what you want.

dsimcha
+4  A: 

I rarely see a need for it, myself.

If my function might need a collection of items, I make it take exactly that: ICollection<> or IEnumerable<>, potentially with an overload that takes a single T for that special case.

If the function is more utilitarian in nature (for example, I have a generic multi-field HashCode generating function), where params might seem to fit, I will still provide quite a few overloads for specific cases like 1 arg, 2 args, 3 args ... sometimes to 5 args or 10 args. Then I will add a catch-all with params. I do this because of the array object creation implicit with params.

qstarin
in .NET 3.5 you can also declare collections inline: new string[] { "one", "two", "three" }; which can help replace the need for params
Aaron Hoffman
+2  A: 

I would avoid using params[] object. What I would do is create a class that encapsulates the three strings in your second overload:

public class HelpStuff
{
   public string Message{get;set;}
   public string Help{get;set;}
   public string ZipCode{get;set;}
}

Then have two overloads like this:

  public static void CallSuperManforHelp(string helpMessage, params string[] kryptonParams)
    {
            //do work
    }

    public static void CallSuperManforHelp(HelpStuff helpStuff)
    {
           //do work
    }
BFree
A: 

If you have this method:

    public static void CallSuperManforHelp(string helpMessage, params object[] kryptonParams) { ... }

you can cool it with these code:

CallSuperManforHelp("please help");
CallSuperManforHelp("please help", (object[])null);

These calling are equivalent. So if you overloading the "CallSuperManforHelp", you should think about calling convenction of these methods.

TcKs
A: 

It's rarely needed, but useful at times - so I wouldn't say it's a best practice to avoid it. Just try to avoid ambiguity.

String.Format is of course the canonical example, and most cases where I use params, it's to pass to String.Format (e.g. a logging method).

Another example from the framework is DataRowCollection.Add: it's useful to be able to add field values without building an object array first:

    DataTable myDataTable;
    ...
    for(...)
    {
        myDataTable.Rows.Add(col1Value, col2Value, col3Value);
    }
Joe
A: 

I wouldn't mix params/regular overloads in that way - I'd only generally use params to add an override that takes additional (unknown at compile time) parameters.

e.g. A normal method, and then one that takes an additional params:

public static void CallSuperManforHelp(string helpMessage);
public static void CallSuperManforHelp(string helpMessage, params object[] kryptonParams);

This eliminates the ambiguity between the overloads.

If you want the two methods you have defined, then you could simply give them different names to avoid any ambiguity and clarify their usage:

public static void CallSuperManforHelpFormatted(string helpMessage, params object[] kryptonParams)
public static void CallSuperManforHelp(string helpMessage ,string sender,string senderZipCode)
Jason Williams