Methods

Methods allow creating reusable blocks of code that define the behavior of a type. They can have multiple parameters and return a value of a given type.

Method Declaration

Methods have optional modifiers, return types, identifiers, and parameters. Listing 2.18 shows how to implement a method.

Listing 2.18 A Method Implementation (MethodCall.cs)
 using System; class MethodCall {    public static int Increment(int myCountValParam)    {       return ++myCountValParam;    }    static void Main()    {       int myCount = 0;       int myIncrement = Increment(myCount);       Console.WriteLine("myCount: {0}\nmyIncrement: {1}",          myCount, myIncrement);       Console.ReadLine();    } } 

The Increment method in Listing 2.18 takes a single parameter, modifies it, and returns a value. Because myCountValParam is a value type, being passed by value, it does not affect the original value myCount, for which a copy was passed to the method. Table 2.4 describes what happens when a value type is passed to a method as a value parameter. Other parameter types are also discussed in the next section.

Method Parameters

Four types of parameters can be used in the parameter list of a method: value, ref, out, and params. By default, all parameters are passed by value and nothing needs to be specified in the method declaration. Listing 2.18 demonstrated a value parameter. Parameters that do not have a modifier are implicitly value parameters. The following sections describe the other parameter types.

ref and value Parameters

When discussing ref parameters, it is important to distinguish what is really happening and how it differs from a value parameter. With a value parameter, a copy of that parameter is passed to the method, but with a ref parameter, a copy of the reference to the value is passed to the method.

Given this, it is important to understand how value types and reference types are passed to methods according to whether that parameter is a ref or value parameter. Table 2.4 shows the type being passed, its parameter type, and a description of the behavior.

Table 2.4. value and ref Parameter Passing
 

ref PARAMETER

value PARAMETER

Reference Type

A copy of a reference to the reference variable of the reference type is passed. The state of the reference type can be changed, which will reflect in both the calling object and called method. The reference can be changed to another object.

A copy of the reference variable to the reference type is passed. The state of the reference type can be changed in the method and will reflect in both the calling object and called method. The reference to the object cannot be changed.

Value Type

A reference to the value type is copied to the method. Changes will reflect in both the calling object and the called method. As the reference only exists for the purpose of the method call, changing which object the reference refers to will have no impact on code outside the method.

The value type itself is copied to the method. Changes in the method are performed on a separate copy, so they will not be seen in the calling method.

Listing 2.19 demonstrates the behavior of ref and value parameters with reference and value types.

Listing 2.19 Reference and Value Types Passed as ref and value Parameters (RefAndVal.cs)
 using System; // custom reference type class CustomRefType {    public int myRefCount; } // main program type class RefAndVal {    // value type passed by reference    public static int IncrementValByRef(ref int myCountValParam)    {       return ++myCountValParam;    }    // reference type passed by value    public static void IncrementRefByVal(CustomRefType myRefType)    {       myRefType.myRefCount++;       myRefType = new CustomRefType();       myRefType.myRefCount = -1;    }    // reference type passed by reference    public static void IncrementRefByRef(ref CustomRefType myRefType)    {       myRefType.myRefCount++;       myRefType = new CustomRefType();       myRefType.myRefCount = -1;    }    static void Main()    {       // value type passed by reference       int myCount     = 0;       int myIncrement = 0;       Console.WriteLine("// Value Type Passed by Reference.");       Console.WriteLine("Before:");       Console.WriteLine("myCount: {0}\nmyIncrement: {1}",          myCount, myIncrement);       myIncrement = IncrementValByRef(ref myCount);       Console.WriteLine("After:");       Console.WriteLine("myCount: {0}\nmyIncrement: {1}",          myCount, myIncrement);       // reference type passed by value       CustomRefType myRefType = new CustomRefType();       Console.WriteLine("\n// Reference Type Passed by Value.");       Console.WriteLine("Before:");       Console.WriteLine("myRefType.myRefCount: {0}",          myRefType.myRefCount);       IncrementRefByVal(myRefType);       Console.WriteLine("After:");       Console.WriteLine("myRefType.myRefCount: {0}",          myRefType.myRefCount);       // reference type passed by reference       myRefType.myRefCount = 0;       CustomRefType myOldRefType = myRefType;       Console.WriteLine("\n// Reference Type Passed by Reference.");       Console.WriteLine("Before:");       Console.WriteLine("myRefType.myRefCount: {0}",          myRefType.myRefCount);       Console.WriteLine("myOldRefType.myRefCount: {0}",          myOldRefType.myRefCount);       IncrementRefByRef(ref myRefType);       Console.WriteLine("After:");       Console.WriteLine("myRefType.myRefCount: {0}",          myRefType.myRefCount);       Console.WriteLine("myOldRefType.myRefCount: {0}\n",          myOldRefType.myRefCount);       Console.ReadLine();    } } 

Listing 2.19 shows the before and after behavior of value parameters passed by reference, reference parameters passed by value, and reference parameters passed by reference. Of the three scenarios, reference parameters passed by reference is the least used. The only reason to pass a reference parameter by reference is if the method needed to change which object the reference type had a reference to. Also, notice that every time a method with a ref parameter is called, the calling program must specify that it is using a ref argument. Otherwise, the compiler will generate an error.

out Parameters

To improve method call efficiency, a method can specify an out parameter, stating that nothing will be passed to the method, but the caller will receive a reference to the out parameter when the method is complete. This differs from ref parameters, where a type must be initialized and passed in as well as passed back out. An out parameter is only passed back to a caller (one-way) but a ref parameter is both passed to the called method and then passed back to the caller (two-way).

In a normal standalone program where no cross-process or network communication is required, the performance benefit of an out parameter is negligible. However, in distributed applications, where types are marshaled across process and network boundaries, such optimizations are welcome. Using the out parameter means that a type is marshaled across the network or process boundary only one time, when a method call returns. However, with a ref parameter, the performance hit is double because the type is marshaled across the network or process boundary two times, one time when the call is made and a second time when the call completes.

You would use an out parameter when a method returns more than one result. Because a method return value returns only a single result, an out parameter would be required for subsequent results. Another reason to use an out parameter is if the return value was being used to return a status code and the method still needed to return a computed result. Not understanding the benefit of an out parameter, people will often define a method with a ref parameter when a method needs to return a value. However, using a ref parameter when the method doesn't use the input value is wasteful and an out parameter would be more efficient, as explained in the preceding paragraph. However, if the method needs the input value to compute results, the method must be defined with a ref parameter. Listing 2.20 shows how to use an out parameter.

Listing 2.20 Using an out Parameter (OutParam.cs)
 using System; class OutParam {    // out value    public static int GetStatus(out string status)    {       status = "Ready";       return 0;    }    static void Main()    {       string status;       int errorCode = GetStatus(out status);       Console.WriteLine("Error Code: {0}", errorCode);       Console.WriteLine("Status    : {0}", status);       Console.ReadLine();    } } 

Notice that the status variable in Listing 2.20 is not initialized. It wouldn't matter if status were initialized because its value would be ignored when passed to the GetStatus method. The only thing that matters is that status will be initialized when GetStatus returns. Also, notice that when calling the method, the caller must specify the argument passed as an out parameter. Otherwise, a compiler error will be generated.

params Parameters

When a method needs to accept a variable number of parameters, or the number of parameters is unknown ahead of time, a method can declare a params parameter. Think about the Console.WriteLine method, which takes a variable number of parameters. It uses the params parameter to accept as many arguments as the code needs to pass. The types accepted by params parameters are either a single-dimension array, a jagged array, or a comma-separated list of values that are compatible types of the params parameter. The params parameter can only be the last parameter in a method's parameter list. Listing 2.21 demonstrates how to use the params parameter.

Listing 2.21 Using the params Parameter (ParamsParam.cs)
 using System; class ParamsParam {    public static string ReadVariableData(params string[] variableData)    {       string resultString = "Input Items: ";       foreach (string data in variableData)       {          resultString += "\n   " + data;       }       return resultString;    }    static void Main()    {       Console.WriteLine(ReadVariableData("one", "two", "three"));       Console.ReadLine();    } } 

The ReadVariableData method in Listing 2.21 doesn't know how many parameters will be sent to it. It could have accepted more or fewer parameters without a problem.



C# Builder KickStart
C# Builder KickStart
ISBN: 672325896
EAN: N/A
Year: 2003
Pages: 165

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