C# Methods : Part II


This article completes our discussion about methods in C#. I assume that you know the basics of the language only. And you have read the C# Methods article ( the first article).

Remember ?

We talk about methods in the first article and we saw how the method solves a small problem. Also we talk about how we can write a method that contains a parameter list and return a value. We also saw what's the different between the parameter and the parameter value. And we discussed how we can call a method.

In this article we will talk about more interesting concepts like passing arguments, variable scope, methods overloading and many other things.

As I said in the first article that a method solve a small problem so that when you find that your method contains a large number of parameters try to develop it again to solve a smaller problem so it will contains a smaller parameter list and that's will help in debugging and fixing any errors.

The parameter-values can be a variables, arrays, expressions no problem just anything that will be finally evaluate to a value.

Important note about Methods :

When you define a method like the following:

private double TestMethod(int x, double y)
{
return x + y;
}

The parameter list of this method takes 2 parameters the first of int type and the second of double type so when you call the method you must specify the parameters-values in the same order, number, and type of the parameter list. So you can't call TestMethod with the first parameter value of double and the second of int.

Understanding how we can pass parameter-values to parameters

There are 2 unique kinds of data types in C#. value-types and reference-types so before we discuss how we can pass parameter values. We must understand these types.

Value-Types

I call it direct types. Why? Ok when you have a variable of type int and you initialize it with a value this value stored in the same memory location of that variable. So they called it a value types because it store the value of that type in their own memory location. This kind of data types store exactly one piece of data so when you go to the memory location of a variable of that type you will find the value directly. C# have built-in value types: int, uint, long, ulong, decimal, float, double, short, ushort, sbyte, byte, char, bool.

Reference-Types

I call it indirect types. Because the memory address of a variable of that type contains only a reference to the stored data. So to get the data of that variable you must first go to the memory address of that variable and there you will find a reference (reference to memory locations) to the data. This kind of data types store more than one piece of data so when you go to the memory location of a variable of that type you will find only a reference to a memory locations of that variable values. C# have built-in reference-types : string, object. Think about it for a minute, you create objects and normally these objects contain maybe a lot of data like a Customer object you can have a CustomerName, Age, E-mail, Phone data that must be stored in that object so when you go to the memory location of that object you will find a reference to these data.

Now after you understand what  a value-type is and what  a reference-type is you must understand how you pass both of them as a parameter-value to a parameter.

Passing parameter-values to parameters

When we pass a variable of value-types to a method's parameter the method takes a copy of that variable only a copy and if the methods change the value these changes will be reflected only on the copy and not on the original value of the variable. That means the original value of the variable remains. Consider the following example of a console application :

static void Main(string[] args)
{
int v = 5;
Console.WriteLine("v value before we call TakeVType {0}",v);
TakeVType(v);
Console.WriteLine("v value after we call TakeVType {0}",v);
Console.ReadLine();
}
static void TakeVType(int x)
{
x *= 4;
Console.WriteLine("x is now {0}", x);
}

What we have here is 2 methods the Main method of the console application and TakeVType method that takes a parameter of integer data type. The first line of this method multiply x by 4 so it will equal to 20. In the Main method we declared a variable called v of type int and initialize it by 5. We get this variable value before we call the method with that variable as a parameter so we get 5 and we call the method to multiply it by 4 and we get 20. Again we call the original variable and we will find it still 5. Just a copy of the variable just a copy. C# pass the value-types by value and reference-types by reference and this is the default. But we can pass value-types by reference when we use the ref keyword let's look at an example.

static void Main(string[] args)
{
int v = 5;
Console.WriteLine("v value before we call TakeRefType {0}",v);
TakeRefType(ref v);
Console.WriteLine("v value after we call TakeRefType {0}",v);
Console.ReadLine();
}
static void TakeRefType(ref int x)
{
x *= 4;
Console.WriteLine("x is now {0}", x);
}

The method TakeRefType takes a parameter-value of type int and as we know that int is a value-type. Here we use the keyword ref just to pass the parameter value by reference. So here in the Main method we declare a variable v and initialize its value to 5, Second we write this value to the console screen and we call the method TakeRefType with v as a parameter-value, Now the value of v will be 20 inside the method and when you finish the method we write to the console screen v value again and here we will find it 20. So from this example we understand that ref keyword pass value-types by reference and that means it give the memory location of the value-type to the method not a copy of the value. Note that we use ref keyword in both method definition and method call and you must specify it every time you call the method.

Now that we understand the concept of value-types and how we pass it to a parameter by-value and by-reference now let's discuss how we can pass by-reference types . Normally C# pass by-reference types by reference and I can't give you example here because I assume that you don't know anything about objects so I will talk about it in my articles about C# objects and believe me we will take more than example because a lot of work with be done this way.

Note that in the Main method we first initialize the variable v with value of 5 because parameters don't take unassigned variables. Try to declare v without initialization and you will get an error telling you " Use of unassigned local variable 'v' ". But if for some reason you want the method to assign the variable there are the out keyword. Let's talk about it.

The out Keyword

When you need a method that takes unassigned variable you will use the out keyword. Let's look at an example after discuss it.

static void Main(string[] args)
{
int v;
TakeOut(
out v);
Console.ReadLine();
}
static void TakeOut(out int x)
x = 5;
x *= 4;
Console.WriteLine("Now x equal to {0}",x);
}

Easy to understand, Right ?

The first line in the Main method declare the v variable but don't initialize it. The next line we call the method TakeOut with v as the parameter-value for the parameter x. Because we specify the out keyword we can initialize the variable inside the method and that exactly what we did. The first line in the TakeOut method initialize the parameter x to value of 5.

Important Note : Why TakeOut method assign the value to x and not to v ? Actually some of my students asked me this question 2 weeks ago. And my reply was "Tell me something, When we create TakeOut method did we know the name of the variable ? ". The parameter nothing more than a place-holder for something you need. You specify the type of that thing that you want. And here we specify a parameter of type int so any variable of type int can be a parameter-value for that parameter. So you must understand that you deal with x as a place-holder for any variable that will come in that place. When we call the method v will replace the x and the method will execute on that way. ok?

So let's go back to TakeOut method. After we assign a value to x we multiply it by 4 so x will be equal to 20. Any variable will go as a parameter-value for the parameter x will be equal to 20.

Method's Local variables existence

Before we talk about local variables we must discuss the next example of a console application.

static void Main(string[] args)
{
for(int x = 0; x <= 5;x++)
{
// I will do nothing here
}
Console.WriteLine(x);
}

If you compile this code you will get the following error " The name 'x' does not exist in the class or namespace 'forloop.Class1' ". Why ?

You must understand that variables are local to the building block that declares it and only that block can use these variables. These building blocks as you might know branching structure, looping structure and methods. Let's compile this example again with a little modification.

static void Main(string[] args)
{
for(int x = 0; x <= 5;x++)
{
Console.WriteLine(x);
}
}

Now this will work because inside the for block we ask the console to print the value of x.

Let's consider the same example with something new. (but I think a lot of you might know it)

class Class1
{
int x = 10;
static void Main(string[] args)
{
for(int x = 0; x <= 5;x++)
{
Console.WriteLine(x);
}
}
}

I think you may heard about classes in C# but just for now let's say that a class in another building block offered by C# and I will discuss it in my articles about OOP.

When you compile this code we will get the same result which we got it from the last example. So what's the difference ? actually I want let you know that if there is a local variable in a block of code (like x in the for loop) and there are a class variable with the same name the building block will use it's local variable and the global or class variable will be hidden while the program control executing the block's code.

If you understand the last 2 examples then you will understand the third one about methods. Let's check it.

class Class1
{
static void Main(string[] args)
{
MethodTest();
Console.WriteLine(x);
}
static void MethodTest()
{
int x = 5;
}
}

Here we call method MethodTest from the Main method and if you compile this code you will get an error informing you that x does not exist in Class1 and I think now you know the reason Because x is local and valid only inside the code of MethodTest. Note that x is created in memory only when the program control reach the method and destroyed when the program control finish executing the method. So let's write the example to compile without any errors.

class Class1
{
static void Main(string[] args)
{
MethodTest();
Console.WriteLine(x);
}
static void MethodTest()
{
int x = 5;
Console.WriteLine(x);
}
}

Note: Method's parameters are local variables to the method and no other methods can use it. You must understand that automatic create-destroy of method's variables are very good for the memory because in our program there are variables which we will need it all the time (while the program is running) and there are variables which we don't need it all the time (like variable x here) so if x local to the method then C# compiler will create it when its execute MethodTest and destroy it when its finish MethodTest. Imagine that x is exists in memory all the program execution time. It will be a load on the memory and maybe with a huge number of variables in one program you will get " Out of memory" thing. But of course there are variables that exists all the execution type of the program and we will talk about it later when you talk about OOP. Another thing the automatic create-destroy local variables must be initialized by the programmer before we can use, Why ? ok think about it for a minute. The compiler needs to know the size of this variable to allocate the right memory amount.

Important Note : There's something called scoping and it's the concept of "Who can see my method, The class that the method created in or the other classes in my program ?" . And because I didn't discuss Objects and Classes yet I will not talk about it here but I will do in the next few articles about Classes and objects in C#.

Method Overloading

Method overloading is something pretty simple and easy. It's just a way to have more than one method having the same name but each method have a different signature but all methods with the same name and it's the most important thing here. Different signature means a different parameters order or different parameters data types or even another set of parameters for each method. So maybe we will have a method called Add that takes 2 integer parameters to add them and other one with the same name that takes 3 integer parameters and a third one which takes 4 double parameters. Let's explain it more by an example.

class Class1
{
static void Main(string[] args)
{
Add(5,6);
Add(5);
Add(5.2,5.8);
Console.ReadLine();
}
static int Add(int x, int y)
{
Console.WriteLine(x + y);
}
static void Add(int x)
{
Console.WriteLine(x + 1);
}
static void Add(double x, double y)
{
Console.WriteLine(x + y);
}
}

Pretty simple The first Add method here takes 2 integer parameters and add them and the second one with the same name takes only one integer parameter to add it to 1. The third one takes 2 double parameters. I think with .NET life is much better. Right ?

So in method overloading you can mix and match any set of parameters for more than one method with the same name and the C# compiler will choose the best method it will see for the parameters values when you want to execute the method. Something you must note here about implicit conversion and method overloading. I assume that you know about implicit conversion and because it needs a lot of pages to explain I prefer to explain it in a separate article. In implicit conversion C# converts the little size types to the bigger types if it needs too. For example we have a method Add which it takes 2 double parameters and if you specify 2 integer variables as a parameter values for the parameters C# will convert int to double because double is bigger than int and that's called a widening conversion. But if you overload the method with a version of int parameters the compiler will choose it.

I think I covered a lot of  good information and concepts that you can use it. In my next articles I will begin introducing OOP with a hundreds of pages.

Thanks and good luck all.


Similar Articles