Methods: Modularization
We learned in Chapter 11 that arrays are a very important programming structure when we need to “store” a collection of data, variables or objects, of the same data type. We saw that arrays in C# are of a fixed size. Once we declare the size of the array, it cannot be altered. Each item in an array can be referenced using its index, which is also called its subscript, and we can use the foreach loop to iterate the array items. With the foreach iteration, we do not need to use a counter as the foreach construct handles the indexing for us. If we wish to reference an index in an iteration, we can use the more traditional for, while, or do while iteration. We also learned that we could cause an IndexOutOfBounds exception if we are not careful in our coding.
Methods: Concepts of Methods and Functions
Follow the code and the flow of events easier.
Find things quicker.
Would we say the right-hand image? We might say that in the right-hand image, there is a sense of organization, there is space to see things, and there is a sense of calm. The left-hand image, we might say, gives a sense of confusion, clutter, and not caring. We do not want our code to look or feel like the left-hand image.
A method is a code block that contains a series of statements. A program causes the statements to be executed by calling the method and specifying any required method arguments.
In C#, every executed instruction is performed in the context of a method. The Main() method is the entry point for every C# application, and it is called by the Common Language Runtime (CLR) when the program is started.
Some Points Regarding Methods
- A method begins with an access modifier. The access modifier will determine the visibility of the method from another class. If we set the access modifier as
public, the method is accessible inside the class it is created in and is available from outside this class
private, the method is only accessible inside the class it is created in
protected, the method is only accessible inside the class it is in or in a class that is derived from the class
internal, the method is only accessible inside the same assembly but not from another assembly
A method access modifier is followed by the method return type. The return type means the data type of the object that is being returned by the method. We can return any of the data types we have looked at, for example, int, float, double, char, string, or bool. Or we can return a type that we have defined. If the method will not return a value, then the return type is said to be void – the keyword void still needs to appear .
The return type is followed by the method name. The method name should follow good coding principles and let the reader know what the method is doing, simply by reading the name.
The method name is followed by open and close brackets ().
Inside the brackets () there may be a list of parameters. The parameters are variables that will hold any values passed to the method. The parameters will have a data type, which will be stated in front of the parameter name. The list of parameters is enclosed in parentheses (). Not every method will accept parameters; they are optional. So the method can contain no parameters – they can be referred to as parameterless methods.
The parentheses () are followed by opening and closing curly braces {}. Inside the curly braces is where the code, business logic, goes.
Methods are coded inside the class but outside the Main method, if there is a Main method in the class.
Examples
- 1.public void CalculateCommission()
Here the access modifier is public.
The method will not return a value; it therefore returns void.
The method name is CalculateCommission.
The method has no parameters, so it takes in no values, no variables or objects.
- 2.private double CalculateCommission()
Here the access modifier is private.
The method will return a value, which is of data type double.
The method name is CalculateCommission.
The method has no parameters, so it takes in no variables or objects – it is parameterless.
- 3.private double CalculateCommission(double salesAmount, double commissionRate)
Here the access modifier is private.
The method will return a value, which is of data type double.
The method name is CalculateCommission.
The method accepts, takes in, two parameters. The first parameter is called salesAmount, which has a data type of double; and the second parameter is called commissionRate, which has a data type of double.
A method can contain one or more statements.
A method name can use any valid identifier that we want.
A method name should not be a C# keyword.
The method name is used to call the method, and when we call the method, we are asking the method to execute its code and then return to the code that made the call.
There is a very important method called Main( ) and it is reserved for the method that begins execution of your program.
After returning from MethodOne(), the next lines of code, indicated as some business logic in the code in Figure 12-4, are executed until the second method, MethodTwo(), is called. When MethodTwo() is called, the application code will again look outside the Main() method, but this time for a method with the name MethodTwo(). When it finds MethodTwo(), it executes the lines of code within it and then returns to the code within the Main() method.
Methods can be kept separate from the main code and called as required.
The methods are coded outside the Main() method.
Methods are small blocks of code, as we can see from the dotted areas in Figure 12-4.
Modern programming style dictates that a method should do one thing and one thing only. Methods that do more than one thing should be split into further methods. As a caveat we need to be mindful that creating every method to do one thing can actually make the code less readable and possibly harder to maintain, so we have to strike a balance and be realistic, and that is part of being a developer. Essentially, we have three types of methods, and we will look at these now to see how they are used, their similarities, and their differences.
Three Types of Methods
Void method
Void method
The code in Listing 12-1 is what we looked at earlier, and we saw that this type of method executed code and did not return any value – it is a void method.
Value method
Value method
The code in Listing 12-2 is what we looked at earlier, and we saw that this type of method executed code and then returned a value. The value it returns is a variable, and the variable must have a data type that matches the return type stated after the access modifier and before the method signature. In this example we are returning a value of type double – it is a value method.
Parameter method
Parameter method
The code in Listing 12-3 is what we looked at earlier, and we saw that this type of method accepted one or more parameters. The parameters are just variables or objects, so they have a data type, and we give them a name of our choosing. The method executes code, which will probably use the variables passed in as parameters. Otherwise, why would we accept the parameters? The method can also return a value, in which case it is also a value method, or it may not return a value, in which case it is also a void method. This is a parameter method.
In Listing 12-2 the return type is a double, so the method is a value method, but it accepts, takes in, no value, so it is also a parameterless method.
In Listing 12-3 the return type is a double, so the method is a value method, and it accepts, takes in, two values of data type double, so it is also a parameter method.
In Listing 12-4 the return type is a void, so the method is a void method, and it accepts, takes in, one value of data type double, so it is also a parameter method .
Void/parameter method
Interestingly all the methods in Listings 12-1, 12-2, 12-3, and 12-4 have the same name, CalculateCommission, but they return different types or accept different parameters. We will talk about this later when we discuss method overloading.
Void Methods
When we call a method, the lines of code within the method are implemented. In Figure 12-4 we saw that when MethodOne() was called, the program looked for MethodOne(), the lines of code were executed, and control of the program was returned to the main program.
When a method does not return a value, it is said to be a void method. The declaration void indicates that the function returns no value to the caller. It is important to realize that every function declaration specifies a return type, even if it’s void.
Void method
The method has an access modifier of public so the method will be available to all code inside the class or from outside the class.
The return type is void so the method will not return any value, and we will therefore not see the last line of code in the method saying return, but we should be aware that the return is still there and the compiler infers it. We can also have the return statement at any position in the method, but code following it will not be executed.
The name of the method is OdometerReading.
The open and close parentheses follow the name and are empty, which means that the method has no parameters, accepts no values.
The open and close curly braces follow the parentheses, and it is between these braces that the business logic, the code, goes.
The business logic code is very simple as it displays a message to the user through the Console.WriteLine() method.
It reads the user input from the console using the Parse() method.
The Parse() method accepts a parameter, which in this case is Console.ReadLine() - in other words, whatever is entered at the console.
The input is converted to an int, as we have used int.Parse() to convert.
Calling the void method
- 1.
Right-click the solution CoreCSharp.
- 2.
Choose Add.
- 3.
Choose New Project.
- 4.
Choose Console App from the listed templates that appear.
- 5.
Click the Next button.
- 6.
Name the project Chapter12 and leave it in the same location.
- 7.
Click the Next button.
- 8.
Choose the framework to be used, which in our projects will be .NET 6.0 or higher.
- 9.
Click the Create button.
- 10.
Right-click the project Chapter12 in the Solution Explorer panel.
- 11.
Click the Set as Startup Project option.
- 12.
Right-click the Program.cs file in the Solution Explorer window.
- 13.
Choose Rename.
- 14.
Change the name to MethodsVoid.cs.
- 15.
Press the Enter key.
- 16.
Double-click the MethodsVoid.cs file to open it in the editor window.
- 17.
In the editor window, add the code in Listing 12-7.
Class template when adding a class
We are now going to use the same code that we created for the Arrays.cs program, but we will make the code more maintainable by creating methods. Our methods for this example will be void methods.
Listing 12-8 is the code from the Arrays.cs program but with the original comments removed and a new comment added for each block of code that will become a method in our new program. This is an example to illustrate that methods can be used to modularize our code, but remember the caveat we mentioned earlier about striking a balance between all methods doing one thing and having readable and maintainable code.
Program code
We will start by creating the variables to be used in the code. The variables will be created at the class level, inside the class and outside any methods. Later we will make local variables rather than class variables.
In creating the class-level variables, we will use the keyword static before each variable data type, because our Main() method is static, but when we study classes and objects in Chapter 13, we will have class-level variables that are not static, but that’s for a later discussion.
In terms of the word static , we will see more about it in Chapter 13, but for now just accept that static means belonging to this class.
Creating variables at the class level means that all the methods of the class will have access to them.
As we are on a chapter about creating and using methods, we will want to have easy access to the variables, but once we understand a bit more about methods, we will change the approach of using class-level variables and make use of local variables instead.
Note
- 18.
Amend the code, as in Listing 12-9, to declare and create the array at the class level, remembering to use the keyword static.
Declare and create the array
- 19.
Amend the code, as in Listing 12-10, to create the variables at the class level. We must add the word static in front of the data type.
Create the variables using the static keyword
Note
Methods are created outside the Main() method but inside the class. We can add the methods above the Main() method or below it. Here we will add the methods below the Main() method, so we need to be careful and make sure to add the methods below the Main() method but still inside the class, which is indicated by the second last curly brace }. The last curly brace } represents the end of the namespace.
- 20.
Amend the code, as in Listing 12-11, to create the first method, which will be called HowManyClaimsAreBeingMade().
Create method 1 outside the Main() method
- 21.
Amend the code, as in Listing 12-12, to create the second method, which will be called CurrentValueOfCounter() .
Create method 2 outside the Main() method
- 22.
Amend the code, as in Listing 12-13, to create the third method, which will be called ReadTheRepairShopId() .
Create method 3 outside the Main() method
- 23.
Amend the code, as in Listing 12-14, to create the fourth method, which will be called WriteRepairShopIdToTheArray() .
Create method 4 outside the Main() method
- 24.
Amend the code, as in Listing 12-15, to create the fifth method, which will be called ReadTheVehiclePolicyNumber() .
Create method 5 outside the Main() method
- 25.
Amend the code, as in Listing 12-16, to create the sixth method, which will be called WriteVehiclePolicyNumberToTheArray() .
Create method 6 outside the Main() method
- 26.
Amend the code, as in Listing 12-17, to create the seventh method, which will be called ReadTheAmountBeingClaimed() .
Create method 7 outside the Main() method
- 27.
Amend the code, as in Listing 12-18, to create the eighth method, which will be called WriteClaimAmountToTheArray() .
Create method 8 outside the Main() method
- 28.
Amend the code, as in Listing 12-19, to create the ninth method, which will be called ReadTheRepairDate() .
Create method 9 outside the Main() method
- 29.
Amend the code, as in Listing 12-20, to create the tenth method, which will be called WriteRepairDateToTheArray() .
Create method 10 outside the Main() method
- 30.
Amend the code, as in Listing 12-21, to create the eleventh method, which will be called DisplayAllItemsInTheArray() .
Create method 11 outside the Main() method
Now we have created the methods, each executing a small amount of code. We can call any method, at any time, from within the Main() method in the program class or indeed from any method. In the next chapter, we will see how we could call the methods from within a different class.
We will now
Call method 1 from within the Main() method.
Add a do while iteration in the Main() method.
Call methods 2–10 from within the do while iteration.
Call method 11 from outside the do while iteration but within the Main() method.
- 31.
Amend the code, as in Listing 12-22.
Create the method calls from within the Main() method
- 32.
Amend the code, as in Listing 12-23, by adding, within the Main() method and outside the do while iteration, a call to the display method.
Call method 11 to display the data
- 33.
Click the File menu.
- 34.
Choose Save All.
- 35.
Click the Debug menu.
- 36.
Choose Start Without Debugging.
- 37.
Click in the console window.
- 38.
Type 2 and press the Enter key.
- 39.
Type RS000001 and press the Enter key.
- 40.
Type VP000001 and press the Enter key.
- 41.
Type 1999.99 and press the Enter key.
- 42.
Type 2021/10/01 and press the Enter key.
- 43.
Type RS000001 and press the Enter key.
- 44.
Type VP001234 and press the Enter key.
- 45.
Type 2500.99 and press the Enter key.
- 46.
Type 2021/10/01 and press the Enter key.
- 47.
Press any key to close the console window.
So now we have refactored our original arrays code and created methods that have small amounts of code. The code is much neater as all we have in the Main() method are a series of calls to the methods. The methods sit outside the Main() method, but still inside the class. This is now a good example of modern programming where methods are an essential feature of maintainable code – it is modularization . With the code being decomposed into small methods, it is a relatively easy process to test these small code blocks. We could improve the code, but this is a great starting point for modularized code.
Value Methods
Void method
Value methods
Value method sample code
The method has an access modifier of public so the method will be available to all code inside the class or from outside the class.
The return type is int so the method will return a variable that must be of data type int, and the last line of code in the method, usually, says return followed by the variable or object name, but remember we read earlier that we can return from anywhere in the method.
The name of the method is GetScoreDetails.
The open and close parentheses () follow the name and are empty, indicating that the method accepts no parameters.
The open and close curly braces follow the parentheses and it is between these braces that the business logic goes.
The code uses the Console.WriteLine() method to display a message for the user.
The user input is then read from the console using the int.Parse() method.
The Parse() method accepts a parameter, which in this case is Console.ReadLine() – in other words, whatever is entered at the console.
The input is converted to an int as we have used int.Parse() to convert.
In the final line of code, the variable is returned, and it is of data type int.
The format for calling the method is by using the method name followed by the open and close parentheses, GetScoreDetails();.
Difference between void and value methods
Void method | Value method | |
---|---|---|
Signature | Will contain the keyword void | Will contain the keyword belonging to the data type being returned |
Code | Will not contain a return keyword in the code | Will contain a return keyword in the code |
- 1.
Right-click the class called MethodsVoid.cs within the Chapter12 project in the Solution Explorer panel.
- 2.
Choose Copy.
- 3.
Right-click the Chapter12 project in the Solution Explorer panel.
- 4.
Choose Paste.
- 5.
Right-click the MethodsVoid – Copy.cs file, which is the copied file.
- 6.
Choose Rename.
- 7.
Name the class MethodsValue.cs.
- 8.
Ensure that the MethodsValue.cs file is open in the editor window.
- 9.
Rename the class in the open editor window from MethodsVoid to MethodsValue.
- 10.
Right-click the Chapter12 project in the Solution Explorer panel.
- 11.
Choose Properties from the pop-up menu.
- 12.
Choose the MethodsValue.cs class in the Startup object drop-down list.
- 13.
Close the Properties window.
In the required methods, change the keyword void to the data type that is to be returned.
In the required methods, add a return statement followed by the variable name being returned as the last line of the method.
Value method called and returned value not assigned to a variable
The answer to our question is no use at all. We need to assign the returned value to a variable or use it in some other way, and we will do this from within the Main() method where the call is made.
- 14.
Amend method 1, HowManyClaimsAreBeingMade(), as in Listing 12-28.
Method 1 return type changed and a return statement added
- 15.
Amend the calling statement in the Main() method to assign the returned value to a variable as in Listing 12-29.
Call the method and assign the returned value to a variable
Looking at this line, we will see there is room for improvement in the code:
The variable numberOfClaimsBeingMade is the class-level variable and we are assigning it the value returned from the method HowManyClaimsAreBeingMade().
The HowManyClaimsAreBeingMade() method uses the same numberOfClaimsBeingMade class-level variable and has assigned it the value entered by the user.
Therefore, we could make the method code better by simply returning the value read in from the console as entered by the user rather than assigning it to the variable. This simple change helps illustrate good coding. We should also understand that variables should be declared, scoped, only where they are required, that is, local scope rather than “global.”
- 16.
Amend the method 1 code to comment the assignment statement and return the converted input as in Listing 12-30.
Comment the assignment and amend the return statement
- 17.
Remove the commented line so the method has the code as in Listing 12-31.
Commented assignment removed
- 18.
Amend method 3, ReadTheRepairShopId(), as in Listing 12-32.
Method 3 return type changed and a return statement added
- 19.
Amend the calling statement in the Main() method to assign the returned value to a variable as in Listing 12-33.
Call the method and assign the returned value to a variable
- 20.
Amend method 5, ReadTheVehiclePolicyNumber(), as in Listing 12-34.
Method 5 return type changed and a return statement added
- 21.
Amend the calling statement in the Main() method to assign the returned value to a variable as in Listing 12-35.
Call the method and assign the returned value to a variable
- 22.
Amend method 7, ReadTheAmountBeingClaimed (), as in Listing 12-36.
Method 7 amended to return a value
- 23.
Amend the calling statement in the Main() method to assign the returned value to a variable as in Listing 12-37.
Call the method and assign the returned value to a variable
- 24.
Amend method 9, ReadTheRepairDate(), to return the user input value as shown in Listing 12-38.
Method 9 return type changed and a return statement added
- 25.
Amend the calling statement in the Main() method to assign the returned value to a variable as in Listing 12-39.
Call the method and assign the returned value to a variable
- 26.
Click the File menu.
- 27.
Choose Save All.
- 28.
Click the Debug menu.
- 29.
Choose Start Without Debugging.
- 30.
Click in the console window.
- 31.
Type 2 and press the Enter key.
- 32.
Type RS000001 and press the Enter key.
- 33.
Type VP000001 and press the Enter key.
- 34.
Type 1999.99 and press the Enter key.
- 35.
Type 2021/10/01 and press the Enter key.
- 36.
Type RS000001 and press the Enter key.
- 37.
Type VP001234 and press the Enter key.
- 38.
Type 2500.99 and press the Enter key.
- 39.
Type 2021/10/01 and press the Enter key.
- 40.
Press any key to close the console window.
So now we have changed some of the methods to make them value methods. A value method means a value, which has a data type, is returned from the method. When creating a value method and we talk about a method signature, the method signature does not contain the data type being returned, but the data type being returned appears before the method name.
This is great. We now have void and value methods within our code, and we will continue with the last main method type, the parameter method, which will also be a void or a value method.
Parameter Methods
It is possible to have our methods accept a value or multiple values and then use these values within the body of the method as part of the business logic processing. We could have a method that accepts two integer values and uses them in a multiplication or a method that accepts a string value and a quote amount and displays the two values. In using a parameter method , we pass it actual values , as arguments, when we call the method. When we are creating the parameter method, the parameters, and their data type, are enclosed as part of the method signature. When the arguments, actual values, are passed to the method, the method accepts these arguments, and their values are assigned to the parameters in the accepting method.
A parameter is a variable or object in a method declaration and should be thought of as a placeholder that will hold the actual value when it is passed to the method from the calling statement.
An argument is the actual value passed to the method, which accepts it.
Think of the a of arguments as actual values.
We say that the method defines the parameters and accepts the arguments.
The right number of input arguments
The correct type of arguments
The correct order of the arguments
Example
Number of items
Cost per item
the result of a multiplication can be produced. The method will use the input data, perform its business logic and calculations, and produce a result.
Parameter method that accepts one parameter
The method has an access modifier of public so the method will be available to all code inside the class or from outside the class.
The return type is double so the method will return a variable that must be of data type double, and therefore the last line of code in the method will contain the keyword return followed by the variable name.
The name of the method is AccumulateClaimAmount.
The open and close parentheses () follow the name and hold two arguments passed to the method, and they are called totalOfAllClaims and claimAmount, which are of data type double.
The open and close curly braces follow the parentheses, and it is between these braces that the business logic is coded.
The business logic adds the variable values that have been passed in and assigns the value to a new local variable called newTotal.
In the final line of code, the newTotal variable is returned to the calling statement and it is of data type double.
Calling the parameter method and passing it a value
Parameter method association with void and value methods
Parameter method | ||
---|---|---|
Signature | May contain the keyword void | May contain the keyword belonging to the data type being returned |
Code | May not contain a return keyword on the last line of code | May contain a return keyword on the last line of code |
Arguments | Will contain one or more arguments |
As we are on a chapter about creating and using methods, we will want to have easy access to the variables, but once we understand a bit more about methods, we will change the approach of using class-level variables and make use of local variables instead.
In the do while construct where we call the method, we are assigning the value returned from the value method to a class-level variable, so we will move the class-level variable to within the do while so it is local.
Change the newly moved variable from having static in front of it, as the do while and therefore this variable are inside a static Main() method.
Next, we will pass the variable to the value method used to write the value to the array; we pass the value as an argument when we call the method.
We then need to make the value method used to write to the array into a parameter method so it can accept the argument being passed to it.
We then will use the parameter of the parameter method in writing to the array rather than using the class-level variable.
- 1.
Highlight the line of code declaring the class-level variable repairShopId, as in Listing 12-42.
Highlight the static variable – repairShopId
- 2.
Right-click and choose Cut.
- 3.
Paste the copied code into the line within the do while construct so we are assigning this copied variable to the value returned from the method ReadTheRepairShopId() , as shown in Listing 12-43.
Static variable is assigned the returned value from the method
- 4.
Remove the keyword static as in Listing 12-44.
Static has been removed from the variable
- 5.
Within the do while construct, call the WriteRepairShopIdToTheArray() method but pass the variable repairShopId as an argument, as in Listing 12-45.
Pass the value as an argument to the method
- 6.
Amend method 4 so that is accepts a string parameter, which we will call repairShopId. Method 4 is now as in Listing 12-46.
Make the method a parameter method
- 7.
Highlight the line of code declaring the class-level variable vehiclePolicyNumber, as in Listing 12-47.
Highlight the static variable – vehiclePolicyNumber
- 8.
Right-click and choose Cut.
- 9.
Paste the copied code into the line within the do while construct so we are assigning this copied variable to the value returned from the method ReadTheVehiclePolicyNumber() and remove the static, as shown in Listing 12-48.
Static variable is assigned the returned value from the method
- 10.
Within the do while construct, call the WriteVehiclePolicyNumberToTheArray() method but pass the variable vehiclePolicyNumber as an argument, as in Listing 12-49.
Pass the value as an argument to the method
- 11.
Amend method 6 so that is accepts a string parameter, which we will call vehiclePolicyNumber . Method 6 is now as in Listing 12-50.
Make the method a parameter method
- 12.
Highlight the line of code declaring the class-level variable claimAmount, as in Listing 12-51.
Highlight the static variable – claimAmount
- 13.
Right-click and choose Cut.
- 14.
Paste the copied code into the line within the do while construct so we are assigning this copied variable to the value returned from the method ReadTheAmountBeingClaimed() and remove the static, as shown in Listing 12-52.
Static variable is assigned the returned value from the method
- 15.
Within the do while construct, call the WriteClaimAmountToTheArray() method but pass the variable claimAmount as an argument, as in Listing 12-53.
Pass the value as an argument to the method
- 16.
Amend method 8 so that is accepts a parameter of type double, which we will call claimAmount. Method 8 is now as in Listing 12-54.
Make the method a parameter method
- 17.
Highlight the line of code declaring the class-level variable claimDate as in Listing 12-55.
Highlight the static variable – claimDate
- 18.
Right-click and choose Cut.
- 19.
Paste the copied code into the line within the do while construct so we are assigning this copied variable to the value returned from the method ReadTheRepairDate() and remove the static, as shown in Listing 12-56.
Static variable is assigned the returned value from the method
- 20.
Within the do while construct, call the WriteRepairDateToTheArray() method but pass the variable claimDate as an argument, as in Listing 12-57.
Pass the value as an argument to the method
- 21.
Amend method 10 so that it accepts a parameter of type double, which we will call claimDate. Method 10 is now as in Listing 12-58.
Make the method a parameter method
These changes have made a real difference to our code because we have reduced the number of class-level variables, made good use of local variables, and used parameter methods. Yes, we could go further and get rid of the other three class-level variables, but for now this is excellent progress, and we can progress with some more parameter methods.
The parameter method will accept two arguments, both of type double.
The values passed in will be the values of the claim being made and the existing total of all claims.
The method will use the values passed into it to find the new total of all the claims being made.
We will create a method that accepts the accumulated total of the claims and works out how much of the accumulated total is value-added tax (VAT).
The VAT amount will be included in the accumulated total, and the formula for the calculation is shown in Listing 12-59.
Formula for calculating value-added tax
- 22.
Add method 12, a new parameter method, as in Listing 12-60.
Add a new parameter method
Add the new method-level variable
- 23.
Amend the code to call the method, passing the claim amount and the current claims total as the arguments, as in Listing 12-62.
Call the parameter method from within the do while construct
Now we need to create
A value method that accepts the total of all claims as a parameter and then determines the VAT based on this value
A method-level variable to hold the VAT value
- A void method that accepts the total of all claims and the VAT amount and displays a confirmation invoice showing the
Total of the claims without VAT
Total amount of VAT
Total of the claims including VAT
- 24.
Amend the code, as in Listing 12-63, to include the method-level variable.
Add an additional local variable to hold the VAT amount
- 25.
Amend the code to add the value and parameter method, method 13, as in Listing 12-64.
Add additional method to determine the VAT amount
- 26.
Amend the code in the Main() method to call the newly created VAT method, passing it the total value of the claims and the VAT amount, as in Listing 12-65.
Call the new method passing it the two arguments
- 27.
Amend the code in the Main() method , as in Listing 12-66, to display the total of all claims.
Display the total of all claims
- 28.
Amend the code to add the new void method, method 14, which accepts the two arguments – it’s a parameter method, as in Listing 12-67.
Create the new method to display the invoice details
- 29.
Amend the Main() method code to call the method as in Listing 12-68.
Call the method to display the total of all claims
Test data
Net amount | VAT amount | Total amount | |
---|---|---|---|
1000 | 200 | 1200 | |
2000 | 400 | 2400 | |
Totals | 3000 | 600 | 3600 |
- 30.
Click the File menu.
- 31.
Choose Save All.
- 32.
Click the Debug menu.
- 33.
Choose Start Without Debugging.
- 34.
Click in the console window.
- 35.
Type 2 and press the Enter key.
- 36.
Type RS000001 and press the Enter key.
- 37.
Type VP000001 and press the Enter key.
- 38.
Type 1200.00 and press the Enter key.
- 39.
Type 2021/10/01 and press the Enter key.
- 40.
Type RS000001 and press the Enter key.
- 41.
Type VP001234 and press the Enter key.
- 42.
Type 2400.00 and press the Enter key.
- 43.
Type 2021/10/01 and press the Enter key.
- 44.
Press any key to close the console window.
So now we have added parameter methods. Some of the parameter methods – methods 4, 6, 8, 10, 12, and 13 – are also value methods because they return a value, but method 14 is a void method and a parameter method.
We now have the trio of methods – void, value, and parameter – within our code. Now we are really beginning to see how code modularization works and how it can help by making the methods do one thing, which can be tested. We are also learning to think about using local variables rather than class-level variables.
Method Overloading
The number of arguments must be different.
For example, vatAmount(double claimAmount, double vatRate)
vatAmount(double claimAmount, double vatRate, string vatCode)
The types of arguments are different.
For example, vatAmount(double claimAmount, double vatRate)
vatAmount(double claimAmount, float vatRate)
The order of arguments is different.
For example, vatAmount(double claimAmount, double vatRate)
vatAmount(double vatRate, double claimAmount)
Method overloading is a form of polymorphism , different forms of the same object. We will now code a new overloaded method to display a different invoice receipt. The new method, method 15, will accept three arguments. It is a parameter method and it is almost the same code as the last display method.
- 45.
Amend the code to add method 15, as in Listing 12-69.
Method with three parameters to display a receipt
- 46.
Amend the Main() method code to call the method as in Listing 12-70.
Call the method to display the new invoice format
- 47.
Click the File menu.
- 48.
Choose Save All.
- 49.
Click the Debug menu.
- 50.
Choose Start Without Debugging.
- 51.
Click in the console window.
- 52.
Type 2 and press the Enter key.
- 53.
Type RS000001 and press the Enter key.
- 54.
Type VP000001 and press the Enter key.
- 55.
Type 1200.00 and press the Enter key.
- 56.
Type 2021/10/01 and press the Enter key.
- 57.
Type RS000001 and press the Enter key.
- 58.
Type VP001234 and press the Enter key.
- 59.
Type 2400.00 and press the Enter key.
- 60.
Type 2021/10/01 and press the Enter key.
- 61.
Press any key to close the console window.
It has the same name as the DisplayInvoiceReceipt method, method 14.
It has three arguments, whereas the other DisplayInvoiceReceipt method, method 14, has two arguments.
Now for something a little different, and I mean different!
C# 7 Local Function
The local function is a feature introduced in C# 7. What we have covered in terms of methods, and methods being created outside the Main() method, applies not just to C# but other languages like Java. We have also seen that it is good practice to modularize our code and use methods that are small and do one thing. This is all part of the concept of clean code and the concept of separation of concern (SOC) . There is also a concept in programming called the SOLID principles , where the S stands for single responsibility, for a class. But maybe we should also think about single responsibility for a method. When we use a Test-Driven Development approach to programming, we are expected to test methods, and we expect those methods to do one thing.
Now, when it comes to methods in C# 7 and above, we can have what is called a local function, which is a function within a method. Sorry. What happened to the “a method should do one thing and we should have separation of concern and clean code that is easy to maintain”? Well, as the developer, we can decide if it is appropriate to use the local function, and we may choose to use it, but we might choose not to use it.
One thing we should remember is that the methods we have used all exist inside a class. We have learned that methods and fields or properties belong to classes and alongside this we can have local variables, which are only accessible within a method and do not need to be accessed in the class or from other classes. “Traditionally,” the method itself is accessible within the class and from outside the class, but C# 7 introduced us to local functions, and C# 8 introduced us to the static local function, both of which we will look at and explore.
Local function
- 1.
Right-click the Chapter12 project.
- 2.
Choose Add.
- 3.
Choose Class.
- 4.
Name the class LocalFunctions.cs.
- 5.
Click the Add button.
- 6.
Create a Main() method within the class, as this was not produced automatically, and delete the unwanted imports, as in Listing 12-72.
Add the Main() method to the class template
- 7.
Right-click the Chapter12 project in the Solution Explorer panel.
- 8.
Choose Properties from the pop-up menu.
- 9.
Choose the LocalFunctions class in the Startup object drop-down list.
- 10.
Close the Properties window.
We will now create a static method called CalculateRepairCostIncludingVAT() that will
Accept a repair cost.
- Return a value based on
The repair cost
The value that will be returned from the local function CalculateVATAmount(), which we will create and which will be passed the variable holding the repair amount.
- 11.
Amend the code to add a CalculateRepairCostIncludingVAT() static method, as in Listing 12-73.
Add the static method CalculateRepairCostIncludingVAT()
- 12.
Amend the CalculateRepairCostIncludingVAT() method to include our local function, as in Listing 12-74.
Create the local function called CalculateVATAmount
We will now amend the Main() method to
Add the method-level variables we need.
Call the CalculateRepairCostIncludingVAT() method, passing it the cost of repair value.
Display a message to show the total cost.
- 13.
Now add code within the Main() method to add the variables we need, as in Listing 12-75.
Add the method-level variables within the Main() method
- 14.
Now call the CalculateRepairCostIncludingVAT method, as in Listing 12-76, passing it the variable for the repair cost and assigning the returned value to a new local variable called costOfRepairWithVAT.
Call the CalculateRepairCostIncludingVAT method and assign it
- 15.
Now display the value returned from the method call, as in Listing 12-77.
Display a message to include the total cost
- 16.
Click the File menu.
- 17.
Choose Save All.
- 18.
Click the Debug menu.
- 19.
Choose Start Without Debugging.
C# 8 Static Local Function
Demonstrate a static local function.
Show that a class-level static variable can be accessed from within a static local function.
Show that outer method variables are not accessible within a static local function.
Move the vatRate variable to the class level and make it private static.
Make the Main() method private.
Make the CalculateRepairCostIncludingVAT() method private.
Make the local function CalculateVATAmount static.
- 20.
Amend the code as in Listing 12-78, which applies the steps set out previously.
Static local function accessing static class variable
Running the code again gives us the same output, as in Figure 12-11, but we have applied the use of static local functions and shown how they can access static class-level variables. The other thing to demonstrate is that static local functions cannot access outer method variables.
- 21.
Amend the code, as in Listing 12-79, to make the formula use the variable costOfRepair, which exists in the Main() method, the outer method.
Amend the formula to use the outer method variable
- 22.
Hover over the red underline on the costOfRepair and note that we are being told that this variable does not exist in the current context, as in Figure 12-12.
- 23.
Change the formula back to its original format.
C# 10 Null Parameter Checking
We have seen how a method can accept parameters, but what would happen if a parameter was null? Well, C# 10 helps us handle this with the introduction of the null parameter checking .
- 1.
Right-click the project Chapter12 in the Solution Explorer panel.
- 2.
Choose Add.
- 3.
Choose Class.
- 4.
Name the class NullParameterChecking.cs.
- 5.
Click the Add button.
- 6.
Create a Main() method within the class, as this was not produced automatically, and delete the unwanted imports, as in Listing 12-80.
Create the Main() method
- 7.
Right-click the Chapter12 project in the Solution Explorer panel.
- 8.
Choose Properties from the pop-up menu.
- 9.
Choose the NullParameterChecking.cs class in the Startup object drop-down list.
- 10.
Close the Properties window.
- 11.
Amend the code to add a variable to hold a string value representing a vehicle registration and assign it a value, as in Listing 12-81.
Add a variable to hold the vehicle registration
We will now amend the code to
- Create a method called DisplayInvoice() , which will accept three values and check if the first value is null:
If the value is null, display an error message.
If it is not null, display a “receipt.”
Call the DisplayInvoice() method and pass it the three values.
- 12.
Amend the code, as in Listing 12-82, to call the DisplayInvoice() method, which we will create next, and pass it three values, the first of which is the variable we set up for the vehicle registration.
Call the DisplayInvoice() method passing in three values
- 13.
Amend the code to create the DisplayInvoice() method outside the Main() method, as in Listing 12-83.
Create the DisplayInvoice() method accepting three values
- 14.
Click the File menu.
- 15.
Choose Save All.
- 16.
Click the Debug menu.
- 17.
Choose Start Without Debugging.
- 18.
Press the Enter key to close the console window.
- 19.
Amend the code to assign null to the variable holding the vehicle registration, as in Listing 12-84.
Make the variable have a null value
- 20.
Click the File menu.
- 21.
Choose Save All.
- 22.
Click the Debug menu.
- 23.
Choose Start Without Debugging.
- 24.
Press the Enter key to close the console window.
C# 10 Null Parameter Checking Approach
- 25.
Amend the code to use the ArgumentNullException.ThrowIfNull() method on the vehicle registration variable, as in Listing 12-85.
Use the ArgumentNullException.ThrowIfNull() method
- 26.
Click the File menu.
- 27.
Choose Save All.
- 28.
Click the Debug menu.
- 29.
Choose Start Without Debugging.
Chapter Summary
Void methods
Value methods
Parameter methods
Overloaded methods
However, we have also used methods in this code that we did not write. In fact, we have been using methods that we did not write from the first program we wrote in this course. The first real line of code we entered was WriteLine();.
WriteLine() is a method. In this line of code, there is no text in the () brackets so no text is written to the console, but a new line is taken. So the WriteLine() method will move to a new line once it prints its content. How does it work? Well, we do not have to worry because we did not write the code and will not have to maintain the method code – it is part of the C# framework. When we go to answer the question, “How does it work?” simply answer it like this: don’t know, don’t care. What this really means is as developers we should not get involved with methods that are developed to help us and have been tested and proved reliable. They work. We just use them to build our application code.
Other examples of methods we did not write but have used in our code include
Write() – Does not move to a new line once it prints its content
ReadLine() – Accepts no arguments
Parse() – Accepts no arguments
nextDouble() – Accepts no arguments
WriteLine("Message") – A parameter method that accepts one argument
Methods
Variables
We also saw that we can have a local function, a function within a method, and we can even make the function a static function. Finally, we looked at the concept of handling a null parameter being passed to a method by using the ThrowIfNull() method, which accepts the parameter being checked.
We are making great progress in our programming of C# applications and we should be proud of our achievements. In finishing this very important chapter, we are ready to look at classes, and while we have increased our knowledge further, we are advancing to our target.