More about Methods

for RuBoard

More about Methods

In this section we look at several other topics pertaining to methods in C#:

  • Parameter passing

  • Variable-length parameter lists

  • Method overloading

  • Operator overloading

Parameter Passing

Programming languages have different mechanisms for passing parameters. In the C family of languages the standard is "call by value." This means that the actual data values themselves are passed to the method. Typically, these values are pushed onto the stack, and the called function obtains its own independent copy of the values. Any changes made to these values will not be propagated back to the calling program. C# provides this mechanism of parameter passing as the default, but C# also supports "reference" parameters and "output" parameters.

Some terminology will help us in the following discussion. Storage is allocated on the stack for method parameters. This storage area is known as the activation record . It is popped when the method is no longer active. The formal parameters of a method are the parameters as seen within the method. They are provided storage in the activation record. The actual parameters of a method are the expressions between commas in the parameter list of the method call.

 int sum = SimpleMath.Add(5, 7);      // actual parameters                                       //are 5 and 7  ...  public static int Add(int x, int y)  {                                    // formal parameters                                       //are x and y     ...  } 

Value Parameters

Parameter passing is the process of initializing the storage of the formal parameters by the actual parameters. The default method of parameter passing in C# is call- by-value , in which the values of the actual parameters are copied into the storage of the formal parameters. Call-by-value is "safe," because the method never directly accesses the actual parameters, only its own local copies. But there are drawbacks to call-by-value:

  • There is no direct way to modify the value of an argument. You may use the return type of the method, but that allows you to pass only one value back to the calling program.

  • There is overhead in copying a large object.

The overhead in copying a large object is borne when you pass a struct instance. If you pass a class instance, or an instance of any other reference type, you are passing only a reference and not the actual data itself. This may sound like "call-by-reference," but what you are actually doing is passing a reference by value.

Reference Parameters

Consider a situation in which you want to pass more than one value back to the calling program. C# provides a clean solution through reference parameters . You declare a reference parameter with the ref keyword, which is placed before both the formal parameter and the actual parameter. A reference parameter does not result in any copying of a value. Instead, the formal parameter and the actual parameter refer to the same storage location. Thus, changing the formal parameter will result in the actual parameter changing, as both are referring to exactly the same storage location.

The program ReferenceMath illustrates using ref parameters. There is a single method, Calculate , which passes back two values as reference parameters.

 // ReferenceMath.cs  public class ReferenceMath  {     public static void Calculate(int x, int y,  ref  int sum,  ref  int prod)     {        sum = x + y;         prod = x * y;     }  } 

Notice the use of the ref keyword in front of the third and fourth parameters. Here is the test program:

 // TestReferenceMath.cs  using System;  public class TestReferenceMath  {     public static void Main(string[] args)     {  int sum = 0, product = 0;  MultipleMath.Calculate(5, 7,  ref  sum,  ref  product);        Console.WriteLine("sum = {0}", sum);        Console.WriteLine("product = {0}", product);     }  } 

Again we need to have the ref keyword in front of the parameters. It is also necessary to initialize the variables before using them as reference parameters.

Output Parameters

A reference parameter is really designed for two-way communication between the calling program and the called program, both passing data in and getting data out. Thus there is a requirement that reference parameters be initialized before their use. In the case we have just looked at, where we are only obtaining output, initializing the variables only for them to be assigned new values is rather pointless. C# provides for this case with output parameters . Use the keyword out wherever you would use the keyword ref . Then you do not have to initialize the variable before use. Within the method you must be sure to assign the out parameter, and you could not use it before such an assignment. The program OutputMath illustrates the use of output parameters.

Method Overloading

In a traditional programming language such as C, you need to create unique names for all your methods. If methods do basically the same thing but apply only to different data types, it becomes tedious to create unique names . For example, suppose you have a FindMax method that can find the maximum of two int or two long or two string. If we need to come up with a unique name for each method, we would have to create method names such as FindMaxInt , FindMaxLong , and FindMaxString .

In C#, as in other object-oriented languages such as C++ and Java, you may overload method names. That is, different methods can have different names, if they have different signatures . Two methods have the same signature if they have the same number of parameters, the parameters have the same data types, and the parameters have the same modifiers (none, ref , or out ). The return type does not contribute to defining the signature of a method.

At runtime the compiler will resolve a given invocation of the method by trying to match up the actual parameters with formal parameters. A match occurs if the parameters match exactly or if they can match through an implicit conversion. For the exact matching rules, consult the C# Language Specification .

The program OverloadDemo illustrates method overloading. The method FindMax is overloaded to take either long or string parameters. The method is invoked three times, for int , long , and string parameters. There is an exact match for the case of long and string . The call with int actual parameters can resolve to the long version, because there is an implicit conversion of int into long .

Modifiers as Part of the Signature

It is important to understand that if methods have identical types for their formal parameters, but differ in a modifier (none, ref , or out ), then the methods have different signatures. The program OverloadHotel provides an illustration. We have two RaisePrice methods. In the first, the hotel is passed as a value parameter. In the second, the hotel is passed as a reference parameter. These methods have different signatures.

 // HotelTest.cs  using System;  public class HotelDemo  {     public static void Main()     {        Hotel ritz = new Hotel("Boston", "Ritz", 100,                               200.00m);        Hotel flop = new Hotel("Podunk", "Flop", 50, 20.00m);        // The Ritz before and after        Console.WriteLine("Before price hike");        ritz.Show();  RaisePrice(ritz, 50.00m);  Console.WriteLine("After price hike");        ritz.Show();        // The Flop before and after -- use ref version        Console.WriteLine("Before price hike");        flop.Show();  RaisePrice(ref flop, 50.00m);  Console.WriteLine("After price hike");        flop.Show();     }  private static void RaisePrice(Hotel hotel,   decimal delta)  {        hotel.cost += delta;        Console.WriteLine("new cost = {0:C}", hotel.cost);     }  private static void RaisePrice(ref Hotel hotel,   decimal delta)  {        hotel.cost += delta;        Console.WriteLine("new cost = {0:C}", hotel.cost);     }  } 

Variable-Length Parameter Lists

Our FindMax methods in the previous section were very specific with respect to the number of parameters ”there were always exactly two parameters. Sometimes you may want to be able to work with a variable number of parameters ”for example, to find the maximum of two, three, four, or more numbers . C# provides a params keyword, which you can use to indicate that an array of parameters is provided. Sometimes you may want to provide both a general version of your method that takes a variable number of parameters and also one or more special versions that take an exact number of parameters. The special version will be called in preference, if there is an exact match. The special versions are more efficient. The program VariableMax illustrates a general FindMax method that takes a variable number of parameters. There is also a special version that takes two parameters. Each method prints out a line identifying itself, so you can see which method takes precedence. Here is the program:

 // VariableMax.cs  using System;  public class VariableMax  {     public static void Main()     {        Console.WriteLine("max of {0}, {1} = {2}",                          5,7,FindMax(5,7));        Console.WriteLine("max of {0}, {1}, {2} = {3}",                          500,5,7,FindMax(500,5,7));        Console.WriteLine("max of {0}, {1}, {2}, {3} = {4}",                          500,5,7,80,FindMax(500,5,7,80));     }     static int FindMax(int a, int b)     {        Console.WriteLine("FindMax with Two Parameters");        return a < b ? b : a;     }  static int FindMax(params int[] args)  {        Console.WriteLine(            "FindMax with Variable Number of Parameters");        int imax = Int32.MinValue;  for (int i = 0; i < args.Length; i++)  {  if (args[i] > imax)   imax = args[i];  }        return imax;     }  } 

Here is the output:

 FindMax with Two Parameters  max of 5, 7 = 7  FindMax with Variable Number of Parameters  max of 500, 5, 7 = 500  FindMax with Variable Number of Parameters  max of 500, 5, 7, 80 = 500 

Operator Overloading

C#, like C++ but unlike Java, supports operator overloading . The idea is that certain method invocations can be implemented more concisely using operators rather than method calls. Suppose we have a class Matrix that has static methods to add and multiply matrices. Using methods, we could write a matrix expression like this:

 Matrix a, b, c, d;  // code to initialize the object references  d = Matrix.Multiply(a, (Matrix.Add(b, c)); 

If we overload the operators + and * , we can write this code more succinctly:

 d = a * (b + c); 

You cannot create a brand new operator, but you can overload many of the existing C# operators to be an alias for a static method. For example, given the static method Add in the Matrix class:

 class Matrix  {  ...  public static Matrix Add(Matrix x, Matrix y)  { 

you can write instead:

  public static Matrix operator+(Matrix x, Matrix y)  

All of the rest of the class implementation code stays the same, and you can then use operator notation in client code. Operator declarations, such as operator+ shown above, must obey the following rules:

  • Operators must be public and static and may not have any other modifiers.

  • Operators take only value parameters and not reference or output parameters.

  • Operators must have a signature that differs from the signatures of all other operators in the class.

The program OperatorOverloadDemo provides a simple example of operator overloading. The + operator is overloaded in the HotelList class to add a hotel to an array of hotels. In C# if you overload a binary operator such as +, the corresponding compound assignment operator += will be overloaded for you automatically by the compiler. Thus, in our test program, we add the hotel objects ritz and sheraton to the list of hotels using the + and += operators.

 // OperatorOverloadDemo.cs  using System;  public class OperatorOverloadDemo  {     public static void Main()     {        HotelList list = new HotelList();        Hotel ritz = new Hotel("Atlanta", "Ritz");        Hotel sheraton = new Hotel("Boston", "Sheraton");  list = list + ritz;   list += sheraton;  list.ShowHotels();     }  } 
for RuBoard


Application Development Using C# and .NET
Application Development Using C# and .NET
ISBN: 013093383X
EAN: 2147483647
Year: 2001
Pages: 158

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net