Learning to Code — Part 5b: Arguments

At the end of the last part of this section, I mentioned that in this article, we were going to discuss arguments. I wanted to verify exactly what arguments were, and found the following, really funny answer by Steven A. Lowe:

An argument ensues when two programmers cannot agree on the parameters.

Anyway, as I wrote previously, an argument is what gets placed in the parentheses either when a method is called, or within the first line of the method itself. While you can specify those right at the point that you call the method, you can also build default values should no argument values be provided when the method is called. If the corresponding arguments are missing, the default values for those parameters will be used.

static int Pow (int x, int y=2) {
int result = 1;
for (int i = 0; i < y; i++) {
result *= x;
}
return result;
}

In the code above, the variable y is declared, has it’s data type set to integer, and is assigned the default value of 2. Meaning, when this method is called, if no value is sent to it for the value of y, it will use it’s default value, which is 2.

static void Main (string[] args) {
Console.WriteLine(Pow(6));
Console.WriteLine(Pow(3,4));
}

So, when the code above is run, it calls the Pow method, but only sends it a value for the variable x (6). Since it doesn’t send it a value for the variable y, y will take the default value of 2.

At this point, I wanted to explain exactly what happens when the code is run and then, I got stuck on what the keyword static really means. After doing some Googling, I found a really great explanation on an extremely useful website called Dot Net Perls. The post explains that when methods are called, you can call them to perform a function, return a value, and then that’s that. You can also establish a new version, or instance, of a class (giving it a name), then call a method within that class, and apply it to that particular instance.

That’s all well and good, but even as I researched this, and knew about the “idea” of calling a method for one time use, versus creating an instance of a class, and then calling the methods within it, I couldn’t quite understand when I would want to do one or the other. I finally came across a video on YouTube by someone called BeSharp in C# called Static Vs Instance variable. After exactly 1 minute into the video, I got it.

I might want to call a method to do something just one time (like multiply some numbers), but I might also want to “store” an overall “thing” in memory that can have something done to it.

For example, if I was creating a patient database for a doctor, I would want to create a new instance of the class (which, in this example, might be called Patient), and then call the various methods within it to add information about that patient (i.e. name, date of birth, address, etc.).

So, in our code, the Main method is not going to have any instances of it created (or constructed, which we’ll see later is an important term). On the first line of the Main method, the Pow method is called, and sends the value 6 to that method. That value is assigned as the value of the variable x. Since it doesn’t send a value for the variable y, y will take the default value set in the Pow method itself, which is 2. Next, the following occurs:

  • A variable called result is created, with a data type of integer, and is assigned the value 1.
  • A for loop starts, where first a variable called i is established, with a data type of integer, and an initial value of 0.
  • The condition to test for is whether the value of i, at this point, 0, is less than the value of the variable y, which has been set to 2.
  • Since, at this point, it is less than 2, the line of code within the loop is run which is the equivalent of result = result * x, or result = 1 * 6, or result = 6.
  • The value of the variable i, currently 0, is incremented by 1, to a value of 1.
  • The condition is tested again and, since 1 is less than 2, the line of code within the for loop is run again, which is the equivalent of result = result * x, or result = 6 * 6, or result = 36.
  • The value of the variable i, currently 1, is incremented by 1, to a value of 2.
  • The condition is tested again and, since 2 is not less than 2, the loop is exited, and the next line of code within the Pow method is run. Since that line says return result; it sends the current value of result, which is 36, back to the point from where it came.
  • When the Pow method was called, it was within the parentheses of Console.WriteLine, and looked like Console.WriteLine(Pow(6));. This means that what ever the final value is after running the method called Pow, and result is returned, print that value to the screen. Therefore, since the final value was 36, 36 gets printed to the screen.

I’m not going to run through the steps of the second calling of the Pow method, sufficed to say that, since that calling gives 2 arguments (namely 3 and 4), the default value for the variable y is not used. The result of running that line of code prints the number 81 to the screen.

An efficiency when it comes to arguments is an ability to not have to remember the order of the parameters when a method is called. Each argument can be given a name that matches the parameter name. So, if we have the following method:

static int Area(int h, int w) {
return h * w;
}

…and then call it as follows:

static void Main(string[] args) {
int res = Area(w: 5, h: 8);
Console.WriteLine(res);
}

The w: 5, h: 8, allows us to be very specific about which variable will receive which value. As a result, you don’t have to worry about the order you put the arguments in when calling the method. So, even if it was written as h: 8, w: 5, it would still work. Just to mention it, when the above code is run, it prints 40 to the screen.

Apparently, there are three different ways of passing arguments to a method when it’s called: by value, by reference and as Output. The first one, by value, is what C# does by default, and what we have been doing so far. Any changes that get made happen within the parameter, without affecting the argument.

static void Sqr(int x) {
x = x * x;
}
static void Main() {
int a = 3;
Sqr(a);
Console.WriteLine(a);
}

In the code above, while x is the parameter of the Sqr method, a is the actual argument passed into it. Running this code does the following:

  • A variable called a is created, with the data type integer, and is set with an initial value of 3.
  • The Sqr method is called, and is sent the argument a, which has a value of 3. In other words, the value 3 is sent to the Sqr method.
  • The Sqr method starts off by creating a variable called x, assigns it the data type integer, and then assigns it the value that came along with the calling which, in this case, was 3.
  • x = x * x, translates into x = 3 * 3, or x = 9.
  • The method is now finished running but, since it’s not set to return a value back to where it was originally called, the code just moves on to the next line after the method was called, which prints the value of the variable a to the screen. Since no value was returned from the method, and the variable a is equal to 3, and that’s what prints to the screen.

In other words, the variable a, was not affected in any way.

Regarding passing by reference, the app states that it:

…copies an argument’s memory address into the formal parameter. Inside the method, the address is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument.

When I look at the code example lower down, it’s the same as the one above, except there is the keyword ref both when the parameter is declared within the method that’s called (i.e. Sqr), as well as where the argument is specified. When run, however, the it prints 9 to the screen. This means that the result of running the code within the Sqr method, is sent back to the place after which it was originally called.

static void Sqr(ref int x) {
x = x * x;
}
static void Main() {
int a = 3;
Sqr(ref a);
Console.WriteLine(a);
}

What confuses me, however, is that there is no return keyword, and the method is set as void, meaning it doesn’t return any value. This seems like it’s a way to send a value back without using the return keyword.

I looked through the comments within the SoloLearn app to understand why you’d use ref versus return or vice versa, and one response says that:

return doesn’t change the parameter itself, while ref does.

What I’m interpreting from this is that the variable called a is not what is actually being sent to the Sqr method when it’s called. The value of a is. So, even if the return keyword was in the method, there’s nothing back at the line where it was originally called telling it what to assign that value to. Another comment cleared it up a bit more:

…the method is just doing an operation, it’s up to you to decide what to with the result.

One last comment that (I think) seals it for me, is:

In C# we can return ONLY ONE parameter from a method. If it is necessary to change two or more parameters, we can use ref

I needed to test this a bit more in Visual Studio to see what the results would be if I used the return keyword instead of the ref keyword. After a few error messages, I got the code to execute with the following:

static int Sqr(int x) {
x = x * x;
return x;
}
static void Main() {
int a = 3;
int b = 4;
int c Sqr(a);
int d Sqr(b);
     Console.WriteLine(c);
Console.WriteLine(d);
}

When I ran this program, it printed 3 on one line, and then 4 on the next, and then I understood. The Sqr method did do it’s thing, and then the first time, the value of x got returned, and was set equal to a new variable (with the integer data type) called c, and the second time, the value of x got returned, and was set equal to a new variable (with the integer data type) called d. Then, these two new variables were printed to the screen as 9 and 16.

It definitely works, but is a much more cumbersome and less efficient way of writing the code because two additional variables need to be created (c and d), and then need to have the values of our initial variables (a and b) assigned to them. The much simpler way would be the following:

static void Sqr(ref int x) {
x = x * x;
}
static void Main() {
int a = 3;
int b = 4;
Sqr(ref a);
Sqr(ref b);
     Console.WriteLine(a);
Console.WriteLine(b);
}

That was definitely a bit of a journey, but I’ve got it now. The last section regarding passing arguments, talks about passing by output. The app describes output parameters as very similar to reference parameters, except that they transfer data out instead of taking data in. This actually looks to be pretty understandable to me. To put it simply, you can store data within a method and then, when that method is called, retrieve it for use.

static void GetValues(out int x, out int y) {
x = 5;
y = 42;
}
static void Main(string[] args) {
int a, b;
GetValues(out a, out b);
}

When the code above is run, first, two variables are initialized called a and b, and their data types are set to integer. It’s worth noting that the way they’re doing it is different that we’ve seen before. Multiple variables are being created (and assigned data types) at the same time. Certainly seems more efficient.

Anyway, the GetValues method is called with the arguments out a and out b. The out keyword is especially important in both the calling of the method, and the method itself. So, here’s what’s happening:

  • The parameter a in the calling of the method, matches up with parameter x in the GetValues method itself. In the same way, the parameter b, matches up with the parameter y.
  • Inside the method, the value of x is set to be 5, and the value of y is set to be 42.
  • Therefore, if x = 5 AND a = x THEN a = 5. Also, if y = 42 AND b = y THEN b = 42.

And that’s it! Just remember, where you had to put the keyword ref in both the calling statement and the method itself, for output parameters, you have to put the keyword out in both the calling statement and the method itself.

That was a lot, and definitely took some experimenting to understand completely. Next up we’ll first talk about method overloading, which is when multiple methods have the same name, but different parameters. Second, we’ll talk about recursion, which is when a method calls itself.

Please let me know if I messed anything up, or if any of my assumptions were waaaay (or even a little) off.

Also, here’s a link to the last article: Learning to Code — Part 5a: Introduction to Methods and Method Parameters.