Topics on Functions
Topics on Functions
Nested Functions
Introduction
As mentioned in our introduction, a function is a section of code that solves a specific problem. Sometimes, you will find out that a function you had created is useful to only one other function. This means that, in this case, only a certain function A calls a certain function B and no other function calls that function B. If you have a function B that only another function A calls, you can create that function B in the body of the unique function A that calls it.
A local function is a function that is created in the body of another function. A function created inside another is also referred to as nested. The C# language provides various options to nest a function. A local function is one of the options.
Practical Learning: Introducing Functions
Control | (Name) | Text | Other Properties |
Label | Width: | ||
TextBox | txtWidth | 0.00 | TextAlign: Right |
Label | Height | ||
TextBox | txtHeight | 0.00 | TextAlign: Right |
Label | Depth | ||
TextBox | txtDepth | 0.00 | TextAlign: Right |
Button | btnCalculate | Calculate Areas | |
Label | Areas _______________ | ||
Label | Front/Back: | ||
TextBox | txtFrontBack | 0.00 | TextAlign: Right |
Label | Left/Right | ||
TextBox | txtLeftRight | 0.00 | TextAlign: Right |
Label | Top/Bottom | ||
TextBox | txtTopBottom | 0.00 | TextAlign: Right |
using System;
using System.Windows.Forms;
namespace Geometry01
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void ProcessAreas()
{
double width = double.Parse(txtWidth.Text);
double height = double.Parse(txtHeight.Text);
double depth = double.Parse(txtDepth.Text);
double frontBackPerimeter = (width + height) * 2;
double leftRightPerimeter = (height + depth) * 2;
double topBottomPerimeter = (width + depth) * 2;
}
}
}
Nesting a Function
You primarily create a local function like any other, as long as you create it in the body of another function. After creating a nested function, call it by its name as we have done for ther others.
Practical Learning: Introducing the Returned Object
using System; using System.Windows.Forms; namespace Geometry01 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } void ProcessAreas() { double width = double.Parse(txtWidth.Text); double height = double.Parse(txtHeight.Text); double depth = double.Parse(txtDepth.Text); double frontBackPerimeter = (width + height) * 2; double leftRightPerimeter = (height + depth) * 2; double topBottomPerimeter = (width + depth) * 2; Display(); void Display() { txtFrontBack.Text = frontBackPerimeter.ToString(); txtLeftRight.Text = leftRightPerimeter.ToString(); txtTopBottom.Text = topBottomPerimeter.ToString(); } } private void btnCalculate_Click(object sender, EventArgs e) { ProcessAreas(); } } }
using System;
using System.Windows.Forms;
namespace Geometry01
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCalculate_Click(object sender, EventArgs e)
{
double width = double.Parse(txtWidth.Text);
double height = double.Parse(txtHeight.Text);
double depth = double.Parse(txtDepth.Text);
double frontBackPerimeter = (width + height) * 2;
double leftRightPerimeter = (height + depth) * 2;
double topBottomPerimeter = (width + depth) * 2;
Display();
void Display()
{
txtFrontBack.Text = frontBackPerimeter.ToString();
txtLeftRight.Text = leftRightPerimeter.ToString();
txtTopBottom.Text = topBottomPerimeter.ToString();
}
}
}
}
Function Overloading
Introduction
The signature of a function is a combination of its name and the type(s) of its parameter(s), if any. The return type and the symbols (such as the parentheses and the curly brackets) are not part of the signature of a function. Since some functions don't take any parameter, the signature of such functions is only the name of the function. Consider the following function:
void Consist() { }
The signature of that function is:
Consist
Consider the following function:
double Consist() { }
The signature of that function is:
Consist
Notice that both functions use the same name. Also notice their return types, void and double. Regarless of the return types, since those functions use the same name and they don't use any parameter, they have the same signature. Consider a function as follows:
int Consist(string characters) { }
If a function uses one parameter, its signature consists of its name and the data type of the parameter, as in:
function-name#parameter-type
As a result, the signature of the above function is:
Count#string
If a function uses two parameters, its signature consists of its name and the data types of the parameters in the order they appear, as in:
function-name#parameter_1-type#parameter_2-type
If a function uses more parameters, its signature consists of its name and the data types of the parameters in the order they appear, as in:
function-name#parameter_1-type#parameter_2-type#parameter_n-type
Practical Learning: Introducing Function Overloading
Control | (Name) | Text |
Label | Number 1: | |
TextBox | txtNumber1a | 0 |
Label | + | |
Label | Number 2: | |
TextBox | txtNumber1b | 0 |
Button | btnCalculate1 | Calculate |
Label | Result: | |
TextBox | txtResult1 | |
Label | Number 1: | |
TextBox | txtNumber2a | 0 |
Label | + | |
Label | Number 2: | |
TextBox | txtNumber2b | 0 |
Label | + | |
Label | Number 3: | |
TextBox | txtNumber2c | 0 |
Button | btnCalculate2 | Calculate |
Label | Result: | |
TextBox | txtResult2 | |
Label | Number 1: | |
TextBox | txtNumber3a | 0 |
Label | + | |
Label | Number 2: | |
TextBox | txtNumber3b | 0 |
Label | + | |
Label | Number 3: | |
TextBox | txtNumber3c | 0 |
Label | + | |
Label | Number 4: | |
TextBox | txtNumber3d | |
Button | btnCalculate3 | Calculate |
Label | Result: | |
TextBox | txtResult3 |
Overloading a Function
Function overloading is the ability to have two or more functions with the same name in the same scope. The primary rule (probably the only rule) is that the overloaded functions cannot have the same signature.
To perform function overloading, each version of the overloaded function must have a different signature. Consider the following code:
// Square double CalculateArea(double side) { return side * side; } // Circle double CalculateArea(double radius) { return radius * radius * 3.14159; }
That code will produce an error. There are two main options you can use to solve function overloading issues. One of the solutions to perform function overloading is that the parameters of the functions use different data types. Here is an example:
double CalculateBiweeklySalary(double yearlySalary) { return yearlySalary / 24.00; } // A full-time employee with a fixed yearly salary double CalculateBiweeklySalary(string monthlySalary) { double salary = double.Parse(monthlySalary); return monthlySalary / 2.00; }
Another option is that each function can use a different number of parameters. Based on this, if you insist on having various functions that use the exact same signature, simply add an extra parameter to some of them and don't use that extra parameter in the function.
Practical Learning: Overloading a Function
using System.Windows.Forms;
namespace ElementaryOperations1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int Add(int a, int b)
{
return a + b;
}
int Add(int a, int b, int c)
{
return a + b + c;
}
int Add(int a, int b, int c, int d)
{
return a + b + c + d;
}
}
}
using System.Windows.Forms; namespace ElementaryOperations1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } int Add(int a, int b) { return a + b; } int Add(int a, int b, int c) { return a + b + c; } int Add(int a, int b, int c, int d) { return a + b + c + d; } private void btnCalculate1_Click(object sender, System.EventArgs e) { int number1 = int.Parse(txtNumber1a.Text); int number2 = int.Parse(txtNumber1b.Text); int result = Add(number1, number2); txtResult1.Text = result.ToString(); } private void button1_Click(object sender, System.EventArgs e) { int number1 = int.Parse(txtNumber2a.Text); int number2 = int.Parse(txtNumber2b.Text); int number3 = int.Parse(txtNumber2c.Text); int result = Add(number1, number2, number3); txtResult2.Text = result.ToString(); } private void button2_Click(object sender, System.EventArgs e) { int number1 = int.Parse(txtNumber3a.Text); int number2 = int.Parse(txtNumber3b.Text); int number3 = int.Parse(txtNumber3c.Text); int number4 = int.Parse(txtNumber3d.Text); int result = Add(number1, number2, number3, number4); txtResult3.Text = result.ToString(); } } }
Control | (Name) | Text |
Label | Original Price: | |
TextBox | txtOriginalPrice | 0.00 |
Button | btnCalculate | Calculate |
Label | Price after Discount: | |
TextBox | txtPriceAfterDiscount |
A Parameter With an Optional Value
Consider the following code:
double originalPrice;
double CalculatePriceAfterDiscount(double discountRate)
{
return originalPrice - (originalPrice * discountRate / 100);
}
We have learned that if a function uses a parameter, when you call that function, you must provide a value for the argument. There is an exception to this rule.
Practical Learning: Using an Optional Value
using System.Windows.Forms; namespace DepartmentStore4 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double originalPrice; double CalculatePriceAfterDiscount(double discountRate) { return originalPrice - (originalPrice * discountRate / 100); } private void btnCalculate_Click(object sender, System.EventArgs e) { double discountRate = 50.00; // 50% originalPrice = double.Parse(txtOriginalPrice.Text); txtPriceAfterDiscount.Text = CalculatePriceAfterDiscount(discountRate).ToString("F"); } } }
class SaleItem
{
public double OriginalPrice;
public double CalculatePriceAfterDiscount(double discountRate = 50)
{
return OriginalPrice - (OriginalPrice * discountRate / 100m);
}
}
using System.Windows.Forms;
namespace DepartmentStore4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double originalPrice;
double CalculatePriceAfterDiscount(double discountRate = 50)
{
return originalPrice - (originalPrice * discountRate / 100);
}
private void btnCalculate_Click(object sender, System.EventArgs e)
{
double discountRate = 50.00; // 50%
originalPrice = double.Parse(txtOriginalPrice.Text);
txtPriceAfterDiscount.Text = CalculatePriceAfterDiscount().ToString("F");
}
}
}
In the same way, you can create a function that uses many parameters and some or all of those parameters can have default values.
If a method uses more than one parameter, you can provide a default value for each and select which ones would have default values. If you want all parameters to have default values, when defining the method, type each name followed by = and followed by the desired value.
Change the code as follows:using System.Windows.Forms;
namespace DepartmentStore4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double originalPrice;
double CalculatePriceAfterDiscount(double discountRate = 50)
{
return originalPrice - (originalPrice * discountRate / 100);
}
double CalculateMarkedPrice(double price = 200.00,
double tax = 5.75,
double discount = 50.00)
{
double markedPrice;
double afterDiscount = price * discount / 100.00;
double taxValue = afterDiscount * tax / 100.00;
markedPrice = afterDiscount + taxValue;
return markedPrice;
}
private void btnCalculate_Click(object sender, System.EventArgs e)
{
txtPriceAfterDiscount.Text = CalculateMarkedPrice().ToString("F");
}
}
}
Rules on Parameters With Optional Values
If a function uses more than one parameter and you would like to provide default values for those parameters, the order of appearance of the arguments is important:
A Parameter by Reference
Introduction
By default, a function can return only 0 or 1 value. Sometimes, you want a function to return more than one value. The C# language provides various solutions. One option is to use a reference to a variable.
Practical Learning: Using an Optional Value
Control | (Name) | Text |
Label | Original Price: | |
TextBox | txtOriginalPrice | 0.00 |
Label | Discount Rate: | |
TextBox | txtDiscountRate | 0.00 |
Label | % | |
Button | btnCalculate | Calculate |
Label | _______________________ | |
Label | Discount Amount: | |
TextBox | txtDiscountAmount | |
Label | Price after Discount: | |
TextBox | txtPriceAfterDiscount |
Passing an Argument by Value
When calling a function that takes one or more arguments, we provide the necessary value(s) for the parameter(s). This is because an argument is always required and the calling function must provide a valid value when calling such a function. This technique of providing a value for the argument is referred to as passing an argument by value.
Practical Learning: Passing an Argument by Value
using System; using System.Windows.Forms; namespace DepartmentStore5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double Subtract(double a, double b) { return a - b; } double CalculateDiscount(double price, double rate) { return price * rate / 100.00; } private void BtnCalculate_Click(object sender, EventArgs e) { double cost = double.Parse(txtOriginalPrice.Text); double dRate = double.Parse(txtDiscountRate.Text); double discount = CalculateDiscount(cost, dRate); double markedValue = Subtract(cost, discount); txtDiscountAmount.Text = discount.ToString("F"); txtMarkedPrice.Text = markedValue.ToString("F"); } } }
Original Price: 124.95 Discount Rate: 25
Introduction to Passing an Argument by Reference
When you declare a variable in a program, the compiler reserves some space for that variable in the computer memory. The location of a variable in memory is referred to as its address. If you supply the argument using its name, the compiler only makes a copy of the argument's value and passes it to the called function. Although the called function receives the argument's value and can use it in any way it wants, it cannot (permanently) change that value. An alternative is to ask the function to modify the value of its parameter. If you want the called function to modify the value of a supplied argument and return the modified value, you can pass the argument using its reference, that is, its address. This is referred to as passing an argument by reference. The C# language provides various options.
Passing a Parameter in
When you are creating a function, you decide whether you want it to use one or more parameters. You indicate that a function will use a parameter as an external value to assist the function in an operation. Most of the time, the function uses a parameter simply to access the value of that parameter. In most of such cases, you don't change the value of the parameter. If you are using a parameter only for the value it is holdinig and you will not change the value of the parameter, such a parameter is said to be passed "in".
To let you indicate that you are passing a parameter in, the C# language provides the keyword in. To apply this keyword, type it on the left side of the data type of the parameter. In the body of the function, you can ignore the parameter. Here is an example:
double Subtract(double a, in double b)
{
double resultDoubled = a * 2;
return resultDoubled;
}
Otherwise, in the body of the function, use the in-parameter anyway you want. Here is an example:
double Subtract(in double a, double b)
{
/* If you judge it necessary, you can change the value
of a regular parameter. Here is an example: */
b = 100;
return a - b;
}
The most important rule is that you cannot change the value of the in parameter in the function; that is, in the body of the function, you cannot assign a value to the in variable. Based on this, the following code will produce an error:
double Subtract(in double a, double b) { /* If you judge it necessary, you can change the value of a regular parameter. Here is an example: */ b = 100; /* You cannot change the value of an "in" parameter: */ a = 200; return a - b; }
When calling a function that uses an in-parameter, you pass the argument exactly as done so far for regular parameters: simply provide a value for the argument. Of course, you can pass the name of a variable that holds the value of the argument. As an option, you can precede the argument with the in keyword.
Practical Learning: Passing an Argument in
using System; using System.Windows.Forms; namespace DepartmentStore5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double Subtract(in double a, in double b) { return a - b; } double CalculateDiscount(in double price, in double rate) { return price * rate / 100.00; } private void BtnCalculate_Click(object sender, EventArgs e) { double cost = double.Parse(txtOriginalPrice.Text); double dRate = double.Parse(txtDiscountRate.Text); double discount = CalculateDiscount(cost, dRate); double markedValue = Subtract(cost, discount); txtDiscountAmount.Text = discount.ToString("F"); txtMarkedPrice.Text = markedValue.ToString("F"); } } }
Original Price: 212.45 Discount Rate: 35
using System; using System.Windows.Forms; namespace DepartmentStore5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double Subtract(in double a, in double b) { return a - b; } double CalculateDiscount(in double price, in double rate) { return price * rate / 100.00; } private void BtnCalculate_Click(object sender, EventArgs e) { double cost = double.Parse(txtOriginalPrice.Text); double dRate = double.Parse(txtDiscountRate.Text); double discount = CalculateDiscount(cost, in dRate); double markedValue = Subtract(in cost, in discount); txtDiscountAmount.Text = discount.ToString("F"); txtMarkedPrice.Text = markedValue.ToString("F"); } } }
Original Price: 324.65 Discount Rate: 15
As mentioned above, most of the time, you are interested in a parameter for the value it is holding, in which case you simply involve the parameter in an operation in the body of the function. In some cases, you may want a function to change the value of a parameter. To offer a solution, the C# language provides the out keyword. As done with the in parameter, when creating a function, to apply an out-parameter, type the out keyword to the left of the data type of the parameter. Here is an example:
void ProcessWithdrawal(out double amount)
{
}
The out-parameter has some rules that go beyond those of the in keyword:
void GetWithdrawal(out double amount)
{
amount = 265.00;
}
Before calling a function that takes an out-parameter, you can first declare a variable for that parameter.Although you can, you don't have to initialize the variable. After declaring the variable, pass that variable in the placeholder of the argument. When calling the function, precede the argument with the out keyword. Here is an example:
double CalculateDiscount(in double price, in double rate, out double final) { final = 0.00; return 1.00; } private void btnCalculate_Click(object sender, EventArgs e) { double sale; double cost = 1.00; double dRate = 2.00; double disc = CalculateDiscount(cost, in dRate, out sale); }
In our example, before calling the function, we first declared a variable for the argument. If you are planning to use the argument only once, you don't have to first declare the variable. In this case, when calling the function, in the placeholder of the argument, type the out keyword, the data type of the parameter, and a name for the argument.
Probably the most important characteristics of the out feature is that, if you change the value of the out parameter (remember that, in the body of the function, you must assign a value to the out-parameter), any modification made on the argument would be kept when the function ends. This characteristic makes it possible for a function to return many values, a feature not normally available to functions.
Practical Learning: Passing an Argument in
using System; using System.Windows.Forms; namespace DepartmentStore5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double Subtract(in double a, in double b) => a - b; double CalculateDiscount(in double price, in double rate, out double final) { double discount = price * rate / 100.00; final = Subtract(price, discount); return discount; } private void btnCalculate_Click(object sender, EventArgs e) { double sale; double cost = double.Parse(txtOriginalPrice.Text); double dRate = double.Parse(txtDiscountRate.Text); double disc = CalculateDiscount(cost, in dRate, out sale); txtDiscountAmount.Text = disc.ToString("F"); txtMarkedPrice.Text = sale.ToString("F"); } } }
Original Price: 198.95 Discount Rate: 20
using System;
using System.Windows.Forms;
namespace DepartmentStore5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
. . .
private void btnCalculate_Click(object sender, EventArgs e)
{
double cost = double.Parse(txtOriginalPrice.Text);
double dRate = double.Parse(txtDiscountRate.Text);
double disc = CalculateDiscount(cost, in dRate, out double sale);
txtDiscountAmount.Text = disc.ToString("F");
txtMarkedPrice.Text = sale.ToString("F");
}
}
}
using System; using System.Windows.Forms; namespace DepartmentStore5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double Subtract(in double a, in double b) => a - b; void CalculateDiscount(in double price, in double rate, out double reduction, out double final) { reduction = price * rate / 100.00; final = Subtract(price, reduction); } private void btnCalculate_Click(object sender, EventArgs e) { double sale; double discount; double cost = double.Parse(txtOriginalPrice.Text); double dRate = double.Parse(txtDiscountRate.Text); CalculateDiscount(cost, dRate, out discount, out sale); txtDiscountAmount.Text = discount.ToString("F"); txtMarkedPrice.Text = sale.ToString("F"); } } }
Original Price: 495.95 Discount Rate: 40
Control | (Name) | Text |
Label | Revenues ____________ | |
Label | All Revenues Sources: | |
TextBox | txtRevenuesSources | 0.00 |
Label | Expenses ____________ | |
Label | Salaries: | |
TextBox | txtSalaries | 0.00 |
Label | Supplies: | |
TextBox | txtSupplies | 0.00 |
Label | Rent: | |
TextBox | txtRent | 0.00 |
Label | txtOtherExpenses: | |
TextBox | txtOtherExpenses | 0.00 |
Button | btnCalculate | Calculate |
Label | ______________________ | |
Label | txtTotalExpenses: | |
TextBox | txtTotalExpenses | |
Label | txtNetIncome: | |
TextBox | txtNetIncome |
As mentioned ealier to our introduction, normally, when a function that takes an argument is called, the argument is accessed by its value. As an alternative, you may want to access a variable using its memory address. To make this possible, the C# language provides a keyword named ref. Besides the out keyword, the ref keyword is another way to pass an argument by reference.
When creating a function that will use a parameter by reference, precede the parameter's data type with the ref keyword. Here is an example:
void SetDeposit(ref double amount)
{
}
One of the similarities between an in and a ref parameters is that, in the body of the function, you can use or ignore the ref-parameter.
Before passing an argument by reference, you must first declare a variable for it. One of the differences between an out and a ref parameters is that you must initialize a ref parameter before passing it to a function (remember that you neither have to declare a variable for an out parameter nor have to initialize it). When calling the function, (you must) precede the argument's name with the ref keyword. Here is an example:
void Something()
{
double deposit = 0.00;
SetDeposit(ref deposit);
}
As mentioned for an out parameter, in the body of a function that uses a ref parameter, you can change the value of the parameter by assigning a new value to it. Here is an example:
void SetDeposit(ref double amount)
{
amount = 450;
}
As seen for an out-parameter, when a ref argument has changed, when the function ends, the ref argument keeps its new value.
You can create a function that uses 0, one, or more parameters as reference(s). When we studied the fact that a function can return a value, we saw that a function can return only one value because there is only one return keyword. Fortunately, the ability to use many parameters as references makes it possible for a function to return many values.
You can create a function that receives regular parameters and parameters by reference. This creates a lot of flexibility in your applications.
Practical Learning: Passing Argument by Reference
using System; using System.Windows.Forms; namespace BusinessAccounting2 { public partial class BusinessAccounting : Form { public BusinessAccounting() { InitializeComponent(); } double Add(double a, double b, double c, double d) { return a + b + c + d; } double Subtract(double a, double b) { return a - b; } void Prepare(ref double x, ref double y) { double rent = Convert.ToDouble(txtRent.Text); double supplies = Convert.ToDouble(txtSupplies.Text); double salaries = Convert.ToDouble(txtSalaries.Text); double revenues = Convert.ToDouble(txtRevenuesSources.Text); double otherExpenses = Convert.ToDouble(txtOtherExpenses.Text); x = Add(salaries, supplies, rent, otherExpenses); y = Subtract(revenues, x); } private void btnCalculate_Click(object sender, EventArgs e) { ref double totalExpenses = 0.00; ref double netIncome = 0.00; Prepare(ref totalExpenses, ref netIncome); txtTotalExpenses.Text = totalExpenses.ToString("F"); txtNetIncome.Text = netIncome.ToString("F"); } } }
All Revenues Sources: 1528665 Salaries: 535775 Supplies: 12545 Rent: 12500 Other Expenses: 327448
|
||
Previous | Copyright © 2001-2021, C# Key | Next |
|