turbopowerdmaxsteel 0 Report post Posted August 3, 2007 The programming model has gone through many refinements, each change improving upon the model. One of the early changes was the inclusion of Subroutines or Subprograms. As the names suggest, these are fragments of code within a program. They offer the following advantages:- Reduction of code duplication by offering re-usability Simplifying program logic by decomposing the program into smaller blocks Improving readability of the program Why do we need functions? Consider the following program:- using System;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { int JoinDay; Console.WriteLine("Enter the day of Joining:"); JoinDay = Convert.ToInt32(Console.ReadLine()); switch (JoinDay) { case 1: Console.WriteLine("You Joined on a Sunday"); break; case 2: Console.WriteLine("You Joined on a Monday"); break; case 3: Console.WriteLine("You Joined on a Tuesday"); break; case 4: Console.WriteLine("You Joined on a Wednesday"); break; case 5: Console.WriteLine("You Joined on a Thursday"); break; case 6: Console.WriteLine("You Joined on a Friday"); break; case 7: Console.WriteLine("You Joined on a Saturday"); break; } int ResigDay; Console.WriteLine("Enter the Resignation Date:"); ResigDay = Convert.ToInt32(Console.ReadLine()); switch (ResigDay) { case 1: Console.WriteLine("You Resigned on a Sunday"); break; case 2: Console.WriteLine("You Resigned on a Monday"); break; case 3: Console.WriteLine("You Resigned on a Tuesday"); break; case 4: Console.WriteLine("You Resigned on a Wednesday"); break; case 5: Console.WriteLine("You Resigned on a Thursday"); break; case 6: Console.WriteLine("You Resigned on a Friday"); break; case 7: Console.WriteLine("You Resigned on a Saturday"); break; } Console.ReadLine(); } }}This program displays the weekday of joining and resigning based on the day code entered by the user. While, there are no errors in the code, there is a problem - repetition of code. The switch block in the second case (Resignation Day) is more or less the same except for the prefix to the output message being You Resigned on a . Looping is meant to minimize code repetition, but it is not applicable everywhere. In scenarios such as these we should use functions to reduce code repetition. Below is the same program when done by using a function. using System;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { int JoinDay; Console.WriteLine("Enter the day of Joining:"); JoinDay = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("You Joined on a {0}", GetDayFromCode(JoinDay)); int ResigDay; Console.WriteLine("Enter the Resignation Date:"); ResigDay = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("You Resigned on a {0}", GetDayFromCode(ResigDay)); Console.ReadLine(); } public static string GetDayFromCode(int Code) { switch (Code) { case 1: return "Sunday"; case 2: return "Monday"; case 3: return "Tuesday"; case 4: return "Wednesday"; case 5: return "Thursday"; case 6: return "Friday"; case 7: return "Saturday"; default: return ""; } } }}We have saved 28 lines by using the function for just 2 cases - Date of Joining & Resigning. Note: - We haven't added provision for handling invalid day codes i.e values not belonging to the range 1 - 7. The terms function and methods are used interchangeably. Functions are composed of statements that are grouped under a name and can be used repeatedly by just calling the function. Declaration Before we can use a function, we need to define its properties, what it does and the value that it returns. Any function declaration has two parts - Signature and Body. We will use this function as our example to study the two parts. public int SumOfTwoNumbers(int Num1, int Num2){ int Sum = Num1 Num2; return Sum;} Function Signature The function signature is composed of the Return Type, Function Name and the optional Parameters and Access Specifier. Return TypeThe return type determines the type of value that the function will return. It can be any of the atomic data types (int, char, string, bool, float, etc) or the user defined types (enums, objects, structures). A function that does not return any value should have a return type of void. Function NameThe function name can be anything that follows the naming rules:- The name must begin with a letter or an underscore & can be followed by a sequence of letters (A-Z), digits (0-9) or underscore (_) Special Characters such as ? - * / \\ ! @ # $ % ^ ( ) [ ] { } , ; : . cannot be used in the function name. A function name must not be the same as a reserved keyword such as using, public, etc.The name can contain any number of the allowed characters.Functions with the same class cannot have the same name ParametersFunctions take values as input, process it and return the output. These inputs are in the form of parameters. The parameters themselves are composed of the data type and the parameter name. The data type restricts the values that can be passed to the function (int only allows Integer values, bool allows Boolean values and so on) and the parameter name can be used like a regular variable under the function body. This variable would be initialized with the value that is passed to the function when it is invoked (called). A function can have any number of parameters each of which need to separated by a comma. Function Body This is where we define what the function actually does. In our case, the body is composed of the lineint Sum = Num1 Num2; which does the actual calculation and return Sum which returns the value to the calling function. Every function (except the constructor and destructor) which doesn't have a return type of void must return a value. The return value must comply with the data type specified in the signature. Calling/Invoking the function By calling/invoking the function, we imply using it - which results in the lines of code written inside it being executed. Calling a function is very simple. We do so by the following syntax:- FunctionName(param1, param2 ...); In our case, it would go something like - SumOfTwoNumbers(6, 9);. This line will pass the execution to the function SumOfTwoNumbers along with the values 6 and 9 which will get copied in the variables Num1 and Num2. After this, the line int Sum = Num1 Num2; will be executed and the sum of the two numbers will be stored in the variable Sum. Finally, this value will be returned to the calling function, which basically discards this value (as of now). We can store this result as int MySum = SumOfTwoNumbers(6, 9); or display it on screen as follows Console.WriteLine(SumOfTwoNumbers(6, 9));. Special Cases A parameter can have two variations - ref and out. When these prefixes are applied to any parameter, its behaviour changes. Normally, the values passed to the function are just copies of the original value and any changes made to this value have no effect on the original value. By using the ref keyword we can force the value to be passed by reference. This creates an alias of the variable which might have a different name but points to the same address in the memory. Thus, changes made to this value reflect in the original value. The swap function is a trivial example of this difference:- using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { int A = 10, B = 20; Console.WriteLine("The value of A = {0} and B = {1}", A, B); Swap(A, B); Console.WriteLine("The value (after swapping) of A = {0} and B = {1}", A, B); Console.ReadLine(); } public static void Swap(int A, int B) { int Temp = A; A = B; B = Temp; Console.WriteLine("The value (during swapping) of A = {0} and B = {1}", A, B); } }}The output of the following program would be:- The value of A = 10 and B = 20 The value (during swapping) of A = 20 and B = 10 The value (after swapping) of A = 10 and B = 20 As you can see, the changes made to the value of A and B inside the Swap function have no effect on the values of A and B inside the Main function. This is because both pairs of variable belong to their scopes (the Swap function and the Main Function) and are hence separate. However, by using the ref keyword, we can point the variable A inside the Main and Swap function to the same memory location (same holds for the variable B ). The variable A inside the Swap function will be called an alias of the variable A inside the Main function. The alias doesn't need to have the same name either. The alias stores the memory address of the original variable and not its value. using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { int A = 10, B = 20; Console.WriteLine("The value of A = {0} and B = {1}", A, B); Swap(ref A, ref B); Console.WriteLine("The value (after swapping) of A = {0} and B = {1}", A, B); Console.ReadLine(); } public static void Swap(ref int A, ref int B) { int Temp = A; A = B; B = Temp; Console.WriteLine("The value (during swapping) of A = {0} and B = {1}", A, B); } }}Output:- The value of A = 10 and B = 20 The value (during swapping) of A = 20 and B = 10 The value (after swapping) of A = 20 and B = 10 By using the ref keyword, we have made the change persistent inside the Main function. Note: It is necessary to specify the ref keyword during function calling. A function can take multiple inputs but only return a single value. There might be situations when we need multiple values as output from the function. We can do this by using either the ref or the out keyword. Both of them result in references being passed. The only difference is that the out keyword passes along null values and is hence ideally suited for output purposes. Note: It is necessary to specify the out keyword during function calling. Previous Tutorial - Lesson 7 - Creating Value Types & Reference Types - Part II Lesson: 1 2 3 4 5 6 7 Share this post Link to post Share on other sites