This project has moved. For the latest updates, please go here.
The following rules outline the usage guidelines for methods:
  • Choose a name for your event based on the recommended Method Naming Guidelines.
  • Do not use Hungarian notation.
  • By default, methods are nonvirtual. Maintain this default in situations where it is not necessary to provide virtual methods. For more information about implementing inheritance, see Base Class Usage Guidelines.

Method Overloading Guidelines

Method overloading occurs when a class contains two methods with the same name, but different signatures. This section provides some guidelines for the use of overloaded methods.

Use method overloading to provide different methods that do semantically the same thing.
Use method overloading instead of allowing default arguments. Default arguments do not version well and therefore are not allowed in the Common Language Specification (CLS). The following code example illustrates an overloaded String.IndexOf method.

int String.IndexOf ( String name );
int String.IndexOf ( String name, int startIndex );
  • Use default values correctly. In a family of overloaded methods, the complex method should use parameter names that indicate a change from the default state assumed in the simple method. For example, in the following code, the first method assumes the search will not be case-sensitive. The second method uses the name ignoreCase rather than caseSensitive to indicate how the default behavior is being changed.

// Method #1: ignoreCase = false.
MethodInfo Type.GetMethod ( String name ); 
// Method #2: Indicates how the default behavior of method #1 is being // changed.
 MethodInfo Type.GetMethod ( String name, Boolean ignoreCase );

Use a consistent ordering and naming pattern for method parameters. It is common to provide a set of overloaded methods with an increasing number of parameters to allow the developer to specify a desired level of information. The more parameters that you specify, the more detail the developer can specify. In the following code example, the overloaded Execute method has a consistent parameter order and naming pattern variation. Each of the Execute method variations uses the same semantics for the shared set of parameters.

public class SampleClass {
   readonly string defaultForA = "default value for a";
   readonly int defaultForB = "42";
   readonly double defaultForC = "68.90";
   
   public void Execute ( ) {
      Execute ( defaultForA, defaultForB, defaultForC );
   }
            
   public void Execute ( string a ) {
      Execute ( a, defaultForB, defaultForC );
   }
         
   public void Execute ( string a, int b ) {
      Execute ( a, b, defaultForC );     
   }
   
   public void Execute ( string a, int b, double c ) {
      Console.WriteLine ( a );
      Console.WriteLine ( b );
      Console.WriteLine ( c );
      Console.WriteLine ( );
   } 
}
Note that the only method in the group that should be virtual is the one that has the most parameters and only when you need extensibility.
  • If you must provide the ability to override a method, make only the most complete overload virtual and define the other operations in terms of it. The following example illustrates this pattern.

public class SampleClass {
   private string myString;

   public MyClass ( string str ) {
      this.myString = str;
   }
   
   public int IndexOf ( string s ) {
      return IndexOf ( s, 0 );
   }

   public int IndexOf ( string s, int startIndex ) {
      return IndexOf ( s, startIndex, myString.Length - startIndex );
   }

   public virtual int IndexOf ( string s, int startIndex, int count ) {
      return myString.IndexOf ( s, startIndex, count );
   }
}

Methods With Variable Numbers of Arguments

You might want to expose a method that takes a variable number of arguments. A classic example is the printf method in the C programming language. For managed class libraries, use the params keyword for this construct. For example, use the following code instead of several overloaded methods.

void Format ( string formatString, params object [] args );

You should not use the VarArgs or ellipsis (...) calling convention exclusively because the Common Language Specification does not support it.

For extremely performance-sensitive code, you might want to provide special code paths for a small number of elements. You should only do this if you are going to special case the entire code path (not just create an array and call the more general method). In such cases, the following pattern is recommended as a balance between performance and the cost of specially cased code.

void Format ( string formatString, object arg1 );
void Format ( string formatString, object arg1, object arg2 );
void Format ( string formatString, params object [] args );

Last edited Jul 19, 2010 at 11:56 AM by camalot, version 1