These notes may remind you of various ways to pass parameters/arguments/values to/from methods/functions/subroutines in C# programs. The same sorts of mechanisms are available in other languages, and as an exercise in understanding you might like to develop a similar document for C, C++ or Pascal.
This material should already be known if you have received a thorough course in C# programming. Please work through it and make sure you understand it completely.
Many programs use this form of parameter passing. "Formal parameters" used in a method heading are effectively "local variables" within that method: when the method is called they are initialised to the values of the expressions evaluated and used as "arguments" or "actual parameters" for that particular call.
Changes made within the method to the formal parameters are "not seen" in/by the calling routine.
class KidsStuff { static int i, j, k, x, y, z; // global variables (never used here) void Function(int i) { // one parameter passed by value IO.Write(i * i); // can access the value of the actual argument(s) } // Function int Sum(int i, int j) { // two parameters passed by value // Sum can access the values of the actual arguments i++; j = 300; // Sum can even alter its local variables i and j return i + j; // a non-void function must "return" a value specified by // an expression after the keyword "return" } // Sum IntSet NewSet(IntSet s, int i) // two parameters passed by value IntSet n = new IntSet(12, 13); // s, i and n are entirely local to NewSet n.Incl(i); return n.Union(s); // a non-void function must "return" a value specified by } // NewSet // an expression after the keyword "return" static void Main(string[] args) { Function(12); // will write 12 * 12 that is, 144 int s = Sum(5, 6); // s will be assigned 306 (work it out for yourself) IntSet ss = new IntSet(5, 8, 9); // ss will be created as the set { 5, 8, 9 } IntSet nn = NewSet(ss, 4); // nn will be assigned the set { 4, 5, 8, 9, 12, 13 } } // Main } // class KidsStuff
Many programs use this form of parameter passing to transfer values both into and also out of a method when it is called and later returns. The formal parameters provide references (in low-level terms, pointers to or the addresses of) the variables used as "arguments" or "actual parameters" when the method is called.
Any changes made within the method to the formal parameters are thus effectively changes to the variables used for the arguments or formal parameters. Note the use of the key word ref in both the caller and the called parameter list.
class KidsStuff { void RefSwap(ref int i, ref int j) { // two parameters passed by reference // actual parameters must be designated as variables int temp; // temp is entirely local to the RefSwap method temp = i; i = j; j = temp; // changes to i and j are changes to the variables used // as actual parameters or arguments // the net result is that the exchange is made } // RefSwap void ValSwap(int i, int j) { // two parameters passed by value // i and j are essentially local to ValSwap // initialised when the function is called int temp; // temp is entirely local to the ValSwap method temp = i; i = j; j = temp; // the net result is that the intended exchange is lost } // ValSwap int RefSum(ref int i, ref int j) { // two parameters passed by reference // can access the value of the actual arguments i and j return i + j; // a non-void function must "return" a value specified by // an expression after the keyword "return" } // RefSum int ValSum(int i, int j) { // two parameters passed by value // i and j are essentially local to ValSum // initialised when the function is called return i + j; // a non-void function must "return" a value specified by // an expression after the keyword "return" } // ValSum static void Main(string[] args) { int x = 10 y = 12, z = 14; // x, y, z are local to Main ValSwap(x, y); // x, y still have the values 10, 12 RefSwap(ref x, ref y); // x, y now have the values 12, 10 ValSwap(10, 12); // valid call but nothing changes RefSwap(12, 10) // illegal - actual arguments must be variables z = ValSum(x, y); // z now has the value 22 z = RefSum(ref x, ref y); // z now has the value 22 z = ValSum(10, 12); // z now has the value 22 z = RefSum(10, 12); // illegal - actual argumentss must be variables } // Main } // class KidsStuff
C# allows for what one might think of as contractual parameter passing. "Formal parameters" used in the method heading stand for references to the variables used as "arguments" or "actual parameters" when the method is called. The key word out, used both to mark formal and actual parameters, is a signal that the method being called must compute a value and assign it to the formal parameter.
Any assignments made within the method to the formal parameters marked in this way are thus effectively changes to the variables used as the arguments or formal parameters .
class KidsStuff { void MaxMin(out int max, out int min, int x, int y) // two values passed in; two results passed out by reference // actual parameters for max and min must be designated as variables max = x > y ? x : y; // or if you prefer if (x > y) max = x; else max = y; min = x < y ? x : y; // or if you prefer if (x < y) min = x; else min = y; } // MaxMin static void Main(string[] args) { int i, j, bigger, smaller; // x, y, z are local to Main i = 10; j = 12; MaxMin(out bigger, out smaller, i, j); // bigger has the value 12, smaller has the value 10 MaxMin(out bigger, out smaller, 2 * i, j); // bigger has the value 20, smaller has the value 12 MaxMin(out bigger, out smaller, 25, 8); // bigger has the value 25, smaller has the value 8 MaxMin(bigger, smaller, i, j); // invalid - key word out missing } // class KidsStuff
These are often expedient (useful) but should be used with great caution.
class KidsStuff { static int x, y, z; static IntSet set1, set2; void Function() { // no parameters x = y; // can access and change class "global" variables } // Function int Sum() { // no parameters // can access global variables return x + y; // a non-void function must "return" a value specified by // an expression after the keyword "return" } // Sum IntSet NewSet() { // no parameters // can access class "global" variables return set1.Union(set2); // a non-void function must "return" a value specified by // an expression after the keyword "return" } // NewSet static void Main(string[] args) { Function(); int s = Sum(); IntSet ss = NewSet(); } // Main } // class KidsStuff
Given that the body of a method has access to the "global" variables of the class in which the method is nested. it is possible for methods that are really intended to do one thing to do other things on the sly. These are called methods with side effects, are usually frowned upon, are sometimes convenient, but should be used with great caution.
class KidsStuff { static int count = 0; static int Fibonacci(int m) { // Returns the m-th Fibonacci number count++; // side effect - count the number of times the method is called if (m == 0) return 0; if (m == 1) return 1; return Fibonacci(m - 1) + Fibonacci(m - 2); } // Fibonacci static void Main(string[] args) { IO,WriteLine(Fibonacci(12)); // use the method properly IO.WriteLine(count); // rely on the side effect to give hidden information } // Main } // class KidsStuff