by November 6, 2001 0 comments



Last month, we started off with the concept of classes in C#. In this article, we’ll delve deeper into the fundamentals of methods. We will start off with understanding the various kinds of parameters that can be sent to them.

Parameter types

Parameters are essentially values that are sent to the methods so that they can work upon the data sent to them and computer results. So, if a method is declared as:

class Cbase
{
public int Double(int v)
{
return v*2;
}
}

then, assuming that obj is an object of type Cbase, it can be passed a value as shown below:

int a=2;
int b=obj.Double(a);

In this case, when the method Double is called and passed the value of the variable a, the variable v gets a copy of the value in variable a, that is 2, and then it returns its double that is assigned to the variable b. Such parameters, like the variable a in the above example, which is used to initialize the method’s variable with a copy of its value are termed as in parameters. It should be noted that in parameters work in the same fashion as they do in traditional C/C++. Such parameter passing and calling of methods is also known as call by value since we pass a copy of the value in the variable to the method rather than a reference, that is address, of the variable.

Another kind of parameters that are supported by C# are termed as ref parameters. For those fluent in C/C++, ref parameters and traditional C/C++ pointers are analogous to each other as far as their functionally is concerned. However, the way parameters are indicated to be as ref is how C# brings in its specifics. But before we see how, lets understand the need for ref parameters.

Conventionally, when a variable is passed down to a method, a copy of the variable value is made and passed to the called method from the caller. This way, there are actually two different memory locations containing the same value: one memory location that contains the value in context of the calling method, and one memory location that contains the value in context of the called method. Thus, if we change the value in the called method, the change shall not be reflected back in the caller method since the two values are in two different memory locations. This is how the in parameters are maintained and worked upon in the memory.

However, when using ref parameters, instead of making a copy of the value of the caller, the compiler simply sends, to the called method, the memory address of the value of the calling method. This way, when called method attempts to make a change to the value, it actually looks up the memory location sent down to it, makes a change to the value contained there. When the called method returns, the change is reflected in the calling method. To define a method taking in a ref parameter, we prefix the parameter name with the ref modifier:

public void Method(ref int v)
{
v=*2; // double the value referred (pointed) to by v
}

What this means is that v is going to contain the memory address of an integer variable. To send down the reference, we call the method, as (assuming obj is the object variable):

int data=2;
obj.Method(ref data);

In the caller method, the ref modifier within the braces of the calling method name tells the compiler to send down the memory address of the variable and not send down a copy of its value. Traditionally, this methodology of working with variables and calling method is called call by reference. Thus, when the above call returns, the variable data is going to contain 4.
Finally, the third kind of parameter type in C# is out parameters. They have no one-to-one correspondence in C/C++, though a rough analogy would be a pointer that is solely used to return values from the called methods. However, if you have programmed using COM, then the analogy is straight: C# out parameters function just like COM’s out parameters. So, lets see how.

Just like the ref modifier, in both the called method and the calling method an out parameter is prefixed with the out modifier. So, if we were to define a method using the out parameter, it would be something like this:

public void Method(int v, out in rv)
{
rv=v*2; // double the value
}

and it would be called as (again, assuming obj is the object variable):

int retval, a=2;
obj.Method(a, out retval);

The calling method simple passes down the value to be worked upon as a normal in parameter, and the variable in which the value is expected to be returned is prefixed with the out modifier. When the method is called, the value is doubled (as shown above), and assigned to the out parameter. Thus, when the call returns to the caller, the out parameter contains the doubled value, something similar to one way pointer concept. Anyway, it isn’t necessary that the value of the out parameter be initialized before placing the call to the method which shall assign it some value.

Methods: To hide or not hide

One of the cornerstones of OO programming is the concept of inheritance that establishes the fact that if one class derives itself from another class, then it would also inherit certain members of the class from which it inherited. The class, which is inheriting, is termed as the child class, while the class from which the child class derives is termed as the base class. For more details into understanding this concept of inheritance, refer to the OOPS tutorial on page 170 in the July 2001 PCQuest issue.
Now, it can be possible that base class defines some method and the child class also wants to implement the same. The situation is similar to that shown below:

class Cbase
{
public void MyMethod()
{
Console.WriteLine(“This is the Base class”);
}
}

The child class would inherit the base class as shown below:

class Cchild:Cbase
{
public void MyMethod()
{
Console.WriteLine(“This is the Child class”);
}
}

If you notice, the child class inherits the base class’s MyMethod as a consequence of inheritance. But at the same time, it has also defined and implemented its own version of MyMethod that displays a slightly different message from the base class’s version.

Traditionally, under C++, this would have compiled easily but it does pose a big, invisible problem: the fact that the child class has hidden the implementation of the base class’s MyMethod. But if you attempt to compile this under C#, the compiler would give you a warning explaining the hiding. Thus, to successfully hide the base class method, we use the new modifier while defining the method in the child class:

class Cchild:Cbase
{
new public void MyMethod()
{
Console.WriteLine(“This is the Child class”);
}
}

The use of new modifier tells the compiler that you are aware of the method hiding that is taking place. For those of you who are wondering about what implications method hiding brings about, here’s a little explanation. Since both base and child classes are implementing the same methods, with the same signature, and the child class is inheriting from the base class, it hides the inherited version of the base class MyMethod implementation when it implements its own version prefixed with the new keyword. Thus, when the method is called upon an object of the child class, the child class MyMethod is called:

childobj.MyMethod(); // calls the MyMethod implementation of the child class

However, what if the method is called upon a base class object as shown below:

Cbase obase = new Cchild();
obase.MyMethod();

Now, the compiler has to resolve the reference given by obase that can be of two types: one is the static reference which is what it was declared was, and the second is the dynamic type that is what it is actually pointing to. In this case, the compiler takes up the static reference into play, which is a reference to a base class object and thus, ends up calling the MyMethod in the base class. This behavior can be altered, resulting in the compiler calling up the child class version of the method by using a technique called method overriding. 

Accessing Base Class Members

C# differs from traditional C++ inheritance in the context of how many classes it can inherit. While C++ allowed us to inherit from any number of classes, C# restricts us to one. Thus, since we are inheriting the implemented members of just one base class, its easier for the compiler to allow us to access those members from the child class using the base keyword:

class Cbase
{
private int v;
public Cbase(int I)
{
v=I;
}
public void MyMethod();
}
class Cchild:Cbase
{
public void CallBaseMethod()
{
base.MyMethod(); // call the MyMethod in the base class
}
}

The base keyword in the child class actually represents the base class, and using the dot notation, we can call or work with any member of the base class. Java programmers will find that the base keyword and Java’s super keyword perform the same function. Anyway, moving on, we can use the same base keyword to pass parameters to the base class constructor. All we got to do is use the base keyword in the constructor of the child class. So, for the example above, the child class constructor will be coded something like:

public Cchild(int v) : base (v)
{
// do some initialization here
}

In this case, the use of the base keyword actually results in passing up the parameters to the corresponding base class constructor.

Working with Virtual Functions

We will now take a quick look at working with virtual functions. Let’s see the following
example.

Cbase objbase = new Cchild();
objbase.MyMethod();

Here, Cbase is the base class and Cchild is the child class that is derived from
Cbase, and MyMethod is a method implemented by both the base and child classes. Now, when the call is made to MyMethod on
objbase, the MyMethod implementation of the base class gets called rather than the child class. This is so because the base class reference has two types of references associated with it: one being the static type that is the one it is declared as (in the example above, the static type reference is
Cbase), and the second one is the dynamic type that depends upon the type being referred to. The compiler, in the above example, ends up using the static type of reference. But if we wish that compiler uses the type being referred to currently, we must use the concept of virtual functions.

We’ll explain this in more detail in the next issue. Until then, happy coding.

Kumar Gaurav Khanna runs www.wintoolzone.com

No Comments so far

Jump into a conversation

No Comments Yet!

You can be the one to start a conversation.

<