21 Mar, 2009 · 9 minutes read
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:-
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.
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;
}
The function signature is composed of the Return Type, Function Nameand the optional Parametersand Access Specifier.
This is where we define what the function actually does. In our case, the body is composed of the line int Sum = Num1 + Num2;which does the actual calculation and return Sumwhich 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.
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 SumOfTwoNumbersalong 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));.
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.