So far, this chapter's examples have returned data via the method return. This section demonstrates the options of returning data via method parameters and via a variable number of parameters.
By default, parameters are passed by value, which means that the variable's stack data is copied into the target parameter. For example, in Listing 4.11, each variable that Main() uses when calling Combine() will be copied into the parameters of the Combine() method. Output 4.5 shows the results of this listing.
Listing 4.11. Passing Variables by Value
Even if the Combine() method assigns null to driveLetter, folderPath, and fileName before returning, the corresponding variables within Main() will maintain their original values because the variables are copied when calling a method. When the call stack unwinds at the end of a call, the copy is thrown away.
Reference Parameters (ref)
Consider Listing 4.12, which calls a function to swap two values, and Output 4.6, which shows the results.
Listing 4.12. Passing Variables by Reference
The values assigned to first and second are successfully switched, even though there is no return from the Swap() method. To do this, the variables are passed by reference. The obvious difference between the call to Swap() and Listing 4.11's call to Combine() is the use of the keyword ref in front of the parameter's data type. This keyword changes the call type to be by reference, so the called method can update the original caller's variable with a new value.
When the called method specifies a parameter as ref, the caller is required to place ref in front of the variables passed. In so doing, the caller explicitly recognizes that the target method could reassign any ref parameters it receives. Furthermore, it is necessary to initialize variables passed as ref because target methods could read data from ref parameters without first assigning them. In Listing 4.12, for example, temp is assigned the value of first, assuming that the variable passed in first was initialized by the caller.
Output Parameters (out)
In addition to passing parameters into a method only (by value) and passing them in and back out (by reference), it is possible to pass data out only. To achieve this, code needs to decorate parameter types with the keyword out, as shown in the GetPhoneButton() method in Listing 4.13 that returns the phone button corresponding to a character.
Listing 4.13. Passing Variables Out Only
Output 4.7 shows the results of Listing 4.13.
In this example, the GetPhoneButton() method returns true if it can successfully determine the character's corresponding phone button. The function also returns the corresponding button by using the button parameter which is decorated with out.
Whenever a parameter is marked with out, the compiler will check that the parameter is set for all code paths within the method. If, for example, the code does not assign button a value, the compiler will issue an error indicating the code didn't initialize button. Listing 4.13 assigns button to _ because even though it cannot determine the correct phone button, it is still necessary to assign a value.
Parameter Arrays (params)
In all the examples so far, the number of parameters is fixed by the target method declaration. However, sometimes the number of parameters may vary. Consider the Combine() method from Listing 4.11. In that method, you passed the drive letter, folder path, and filename. What if the number of folders in the path was more than one and the caller wanted the method to join additional folders to form the full path? Perhaps the best option would be to pass an array of strings for the folders. However, this would make the calling code a little more complex, because it would be necessary to construct an array to pass as a parameter.
For a simpler approach, C# provides a keyword that enables the number of parameters to vary in the calling code instead of being set by the target method. Before the method declaration is discussed, observe the calling code declared within Main(), as shown in Listing 4.14.
Listing 4.14. Passing a Variable Parameter List
Output 4.8 shows the results of Listing 4.14.
In the first call to Combine(), four parameters are specified. The second call contains only three parameters. In the final call, parameters are passed using an array. In other words, the Combine() method takes a variable number of parameters, whether separated by a comma or as a single array.
To allow this, the Combine() method
With a parameter array declaration, it is possible to access each parameter as a member of the params array. In the Combine() method implementation, you iterate over the elements of the paths array and call System.IO.Path.Combine(). This method automatically combines the parts of the path, appropriately using the platform-specific directory-separator-character. (PathEx.Combine() is identical to Path.Combine(), except that PathEx.Combine() handles a variable number of parameters rather than simply two.)
There are a few notable characteristics of the parameter array.
Using a parameter array, you can pass a variable number of parameters of the same type into a method. The section Method Overloading, later in this chapter, discusses a means of supporting a variable number of parameters that are not necessarily of the same type.