Article
Object Oriented C# for ASP.NET Developers
Passing Parameters and Returning Values
Most of the methods we have looked at so far have been of a special type. Here is a declaration of one such method, the PickNut method for the CoconutTree class that we developed above:
public void PickNut() {
numNuts = numNuts - 1;
}
What makes this, and the other methods we have looked at so far, special is the fact that it doesn't require any parameters, nor does it return a value. As you'll come to discover as we look at more practical examples of C# classes later in this series, most methods do one or both of these.
Parameters are pieces of information that must be provided when invoking a function to completely specify the action to be taken. For example, if we wanted to make the PickNut method above more powerful, we could give it a parameter to indicate the number of nuts to be picked:
public void PickNut(int numberToPick) {
numNuts = numNuts - numberToPick;
}
In this new version of the PickNut method, we have specified that the function takes an integer (int) parameter, the value of which is stored in a variable called numberToPick. The code of the method then uses it as the number to be subtracted from the numNuts field. Thus, we can now pick as many nuts as we want from a CoconutTree with a single invocation of the PickNut method. Here are a few sample invocations of PickNut:
CoconutTree ct = new CoconutTree(); // New tree
// Presumably we grow a few nuts first...
ct.PickNut(1); // Picks one nut
ct.PickNut(5); // picks five nuts
ct.PickNut(0); // Doesn't do anything
int nuts = 10;
ct.PickNut(nuts); // Picks ten nuts
ct.PickNut(-1); // Picks -1 nut (??)
As this last line demonstrates, there is a problem with this method. Since it accepts any integer as the number of nuts to be picked, there is nothing stopping a program that uses it to pick a negative number of nuts. Looking at the code of our method, this would actually just add more nuts to the tree, but we should not allow operations on our object that do not make sense in the real world. Another operation that would not make sense would be to pick more nuts than there are available for picking on the tree! With the existing code, this would result in our tree reporting a negative number of nuts -- hardly a realistic situation.
These two problems reveal an important issue when designing methods that require parameters. You should always make sure that the value passed to a method makes sense before using it. Even if you're only planning on using a class in your own programs, it's surprisingly easy to forget what values will and will not cause problems when you aren't checking the values automatically.
The following modified version of PickNut checks the parameter to make sure that it is not negative, and that it is no larger than the number of nuts on the tree:
public void PickNut(int numberToPick) {
if (numberToPick < 0) return; // Cannot pick negative number
if (numberToPick > numNuts) return; // Not enough nuts
numNuts = numNuts - numberToPick;
}
The return command immediately terminates the method. Thus, the operation of picking the nuts (subtracting from the numNuts field) will only occur if both of the conditions in the if statements are false. This ensures that our two constraints are met before we allow the picking operation to go ahead.
One problem still remains, here. How can the code that invokes the PickNut method know whether the picking operation was successful? After all, if the picking operation fails because one of the constraints was not satisfied, we don't want our program to carry on as if it was able to pick the nuts. To resolve this issue, we must once again alter PickNut; this time, we will make it return a value:
public bool PickNut(int numberToPick) {
if (numberToPick < 0) return false;
if (numberToPick > numNuts) return false;
numNuts = numNuts - numberToPick;
return true;
}
Not only can methods receive parameter values when they are invoked, but they can also send a value back by specifying the value as part of the return command. In this new version of the code, we have replaced the word void in the method declaration with the word bool. This indicates that the function will return a Boolean (true/false) value when it terminates. In this particular case, we have elected to return true if the picking operation succeeded, and false if it failed for any reason. This allows us to structure the code of the program that invokes the method as follows:
if (!ct.PickNut(10)) {
ErrorLabel.Text = "Error: Could not pick 10 nuts!";
return;
}
nutsInHand = nutsInHand + 10;
The condition of the if statement calls PickNut with a parameter value of 10, and then checks its return value to see if it's false (note the ! operator). If it is, an error message is printed out. The return command then terminates the Page_Load function immediately, which is a reasonable response to an unexpected error. Otherwise, the program proceeds as usual.
Another common use for return values is to create methods that perform some common calculation and return the result for the program to use. There will be plenty more examples in the rest of this series for you to learn from.