In this lesson, you’re going to learn how to return values from methods that you create. Up to this point, you have been working with methods that return void (in other words, nothing at all). The void keyword means that after the method is called, no information is returned back to the calling code block. However, if you replace the void keyword with a type (int, string, DateTime, etc) you must specify within the method the actual value being returned, and the caller will assume that value once the method it has called completes execution.
Step 1: Recognizing Method Return Values in Intellisense
Some of the helper methods we have been working with thus far have been returning values back to the caller. For example, we know that the int.Parse() method takes in a string, and returns an int. In fact, Intellisense tells us this:
Knowing that int.Parse() returns a value, we can treat it as being that value. Here, we know that the value being returned will be 5, so what can you do with that value? You can do a number of things, and one of them is to assign it to another variable, of type int:
That means that this statement is semantically equivalent to:
And, because those statements are semantically equivalent, you can do this:
Step 2: Create a Custom Method with a Return Type
Let’s create our own custom method with a return type in a new ASP.NET project called “CS-ASP_030”, which is based on where we left off with the previous lesson. In Default.aspx.cs write in some helper methods that we will later reference in Page_Load():
Here again you see the private keyword prefixed to all of these methods. This has to do with whether or not outside classes can access (call) this method/element. This will make sense once you are exposed to Object-Oriented Programming principles in later lessons. However for now know that this keyword means these methods can only be called within the class they’re defined (in this case, the Default class).
Step 3: Calling Methods in the Hero/Monster Page_Load()
These methods should be fairly self-explanatory, however, note that they all just add information to the resultLabel and therefore do not return anything back to the caller. Now, write the following in Page_Load():
Here we are calling the helper methods to display “Battle/Round” header information and then once the battle completes, display the final result. However, this code won’t work properly in its current state, since the while() loop will never break out of just displaying the
“Round” header. We will have to write some battle code so let’s do that in another helper method called performAttack() (also, notice the various input parameters we will be using for this method to work):
This method currently consists of applying a random damage value to defenderHealth, and then returning that value to the caller. However, we’re not yet done with this method. We will also want to execute the describeRound() method within the performAttack() method. When you write the call to describeRound(), you will notice that Intellisense will give you a reminder as to the input parameters you are expected to supply:
When your variables and input parameters have specific, obvious names, it eliminates confusion over ambiguity when referencing them. In this case, we know that describeRound() needs to take in the attacker’s name, defender’s name and the defender’s health. If these weren’t named specifically, their purpose would be unclear.
We will supply these values based on what values are supplied for the outer calling method performAttack(). You can think of it like you are copying these values, whatever they might be, once they are passed in when calling performAttack():
Step 4: Assigning a Method’s Returned Value to a Variable
You can now pass in these values by calling the method in Page_Load(), as follows:
Recall that perfomAttack() returns an integer value, so that is why it’s being assigned to monsterHealth int variable. Finally, we’re reusing this attack procedure, so let’s also make a few more calls to it in the main battle logic within the while() loop:
There are several methods here that each have a specific purpose (and that’s hinted at by the name we chose for each method). This relates to a general programming concept called the “Single Responsibility” principle. Put simply, the more that you break-up your code into individual modules with a single, direct purpose, the easier it will be to keep track of everything in your code and reduce bugs. Each method that you create should have a single specific purpose to keep from complicating the logic in your project. A good practice is to try to keep your method within 10 lines of code.
Step 5: Run the Application
You can now run the application and see the result of this battle simulation: