Advertisment

Virtual Functions and Unsafe Programming

author-image
PCQ Bureau
New Update

This month, we will continue with virtual functions and then go on to abstraction and finally, unsafe programming.

Advertisment

Working with virtual functions

Virtual functions is the mechanism using which the decision, as to which method should be called using which reference, is delayed until runtime. To implement virtual functions, the method in the base class must be prefixed with the virtual keyword, while the method in the child class overrides it using the override keyword prefixed to it:







class Cbase



{


public virtual void MyMethod()


{


// do some stuff


}


}


class Cchild


{


public override void MyMethod()


{


// do some other stuff here


}


}













The use of virtual keyword tells the compiler that the method shall be overridden in the child class and that the call to this method against an object should be resolved at runtime. Assuming the base class method is virtual in nature, then the statements:

Advertisment

Cbase objbase = new Cchild();



objbase.MyMethod();

result in calling the MyMethod implementation of the child class, as opposed to the implementation of the base class that was called in the previous example. Thus, this capability to call method on objects, which are resolved at runtime, is what OO programming terms as polymorphism.

Working with abstraction

Advertisment

There might be situations where one feels that the base class needn’t be instantiated, but child classes could still have their objects created. This is done using the abstract modifier with the class definition as shown below:

abstract class Cbase



{


public void MyMethod()


{


// do some stuff


}


}




When a class is termed as abstract, it cannot be instantiated. However, one can still use references to the same for derived class objects:

Advertisment

Cbase objbase = new Cchild();

assuming Cchild derives from Cbase. But what if the derived class forgets to provide an implementation for the base class methods? In this case, the implementation of the base class method will be called. So, in order to force the derived class to implement all the methods in the abstract class, we prefix the abstract class member methods with the abstract modifier:

abstract class Cbase



{


public abstract void MyMethod


);


}


Advertisment

Now, the derived class has to implement the above method, and thus, we can say that the abstract methods are implicitly virtual in nature since the derived classes have to implement them, more so because in their own class, abstract methods have no implementation defined. In an analogy to C++, abstract methods are something similar to pure virtual 



functions.

To derive or not to derive

There are situations when the class is expected, or should not be derived by its users. C# provides the sealed keyword, which when used with the class definition, prevents the class from being derived. If any attempt is made to derive from the class, a compile-time error occurs:

Advertisment

sealed class Cbase



{


public void MyMethod();


}

Now, the abstract and sealed modifiers, as obvious, are mutually exclusive in nature since the former requires the class to be derived from, while the latter prevents the class from being derived.

A little more of inheritance

Advertisment

We already explained that C# classes can derive only from one other C# class. But then, isn’t that limiting? Actually not. This is so because C# includes another reference type termed as interfaces. Interfaces are quite similar to class, except that they have the interface keyword instead of the class keyword and they can only contain abstract methods, and never contain data members. These abstract methods needn’t be prefixed with the abstract keyword, because any method within the interface definition is expected to be abstract in nature:

interface Ibase



{


void MyMethod();


}

A C# interface is very similar to an abstract C++ base class that contains just pure virtual functions. Hence, they are also very similar to a C# abstract class, containing abstract methods. Thus, one never has an implementation in a C# interface. Interfaces tend to solve the discussed inheritance limitation by allowing C# classes to derive from more than one interface. Interfaces are derived in the same manner as the class inheritance:

class Cchild : Ibase



{


public void MyMethod()


{


// do some coding here


}


}














Interfaces give us two main advantages:

  • They let C# classes have the concept of multiple inheritance
  • They are used to describe behavior. That is, when a class implements one or more interfaces, it will implement methods from both the interfaces. And hence, implement the behavior expected of both the interfaces. Thus, we may pass an object of the class implementing the interfaces, where there is need for either of the two interfaces:

void my_func(Ibase ib)



{


// do some stuff here..


}


Cchild objchild = new Cchild();


my_func(objchild);



Access modifiers

Throughout, we have been using access modifiers like public. For those who are not fluent with Java/C++, here’s a brief

explanation of what they do.

There are four kinds of access modifiers in C#:

  • Private: These are used to describe entities that can only be accessed by the class defining them
  • Protected: These are used to describe entities that can be accessed by the class defining them and any of the derived classes
  • Public: These are used to describe entities that can be access by anyone: the class defining them, any of the derived class, and anyone who instantiates the containing class
  • Internal: These are used to describe entities that are common to a given C# assembly. C# assembly is a logical unit of code comprising of the IL code, metadata and more, that might spread across multiple physical files.

Thus, now with a good knowledge of how various class members are to be accessed, you can prefix each of them with an appropriate access modifier.

Properties

To have total control over the modification of private member variables, one traditionally used the concept of accessor methods:

class Cbase



{


private int v;


public void Setval(int I)





// perform any reqd. checking…


v=I;


}


public int Getval()


{


return v;


}


}










One had to explicitly call the methods in order to work with the variable contents. And this wasn’t intuitive either.

C# introduces the concept of properties where one assigns or reads the value of member variables just like they normally do using the dot notation, but internally, the compiler maps them to get/set methods:

class Cbase



{


public int v


{


get


{


return v;


}


set


{


v=value;


}


}


}











value is a special variable that holds the value sent in by the user. The class variable is assigned the value 



as:

objbase.v=10;

Thus, one has total control over the value being assigned. In fact, using either of the two methods (get or set), you can create a read-only or a write-only property.

Unsafe Programming

Now that we are done with the basics of C#, there’s one particular topic that will catch the fancy of most C/C++ programmers: pointers. Most people think that C# carries no concept of pointers. However, unsafe code is that part of C# programming, which is all about programming with pointers. Unlike its literal meaning, there is nothing unsafe about programming with pointers. It is so referred because unsafe programming requires certain assumptions on the part of the programmer. We shall start off by differentiating two highly confused terms, unsafe code and unmanaged code. This will be followed by discussion on how to write unsafe code, that is, how to use pointers in C#.

Unsafe or unmanaged

Managed code is that code which executes under the supervision of the CLR. The CLR is responsible for various housekeeping tasks, like:

  • managing memory for the objects
  • performing type verification
  • doing garbage collection

just to name a few. The user is totally isolated from the hows of the above mentioned tasks. The user doesn’t get to manipulate the memory directly, but that is done by the CLR.

On the other hand, unmanaged code is that code which executes outside the context of the CLR. The best example of this is our traditional Win32 DLLs like KERNEL32.DLL, USER32.DLL, the COM components installed on our system. How they allocate memory for their usage, how memory is released, how (if any) type verification takes places are some of the tasks that are undertaken by them on their own. A typical C++ program which allocates memory to a character pointer is another example of unmanaged code because the programmer is responsible for:

  • calling the memory allocation function
  • making sure that the casting is done right
  • making sure that the memory is released when the work is done

If you notice, all this housekeeping is done by the CLR, as explained above, relieving the programmer of the burden.



Unsafe code is a kind of cross between the managed and unmanaged codes. It executes under the supervision of the CLR, just like the managed code, but lets you address the memory directly, through the use of pointers, as is done in unmanaged code. Thus, you get the best of both worlds. You might be writing a .Net application that uses the functionality in a legacy Win32 DLL, whose exported functions require the use of pointers. That’s where unsafe code comes to your rescue.

Inside unsafe code

Writing unsafe code requires the use of two special keywords: unsafe and fixed. If we recall, there are three kinds of pointer operators:

*



&


->

Any statement, or a block of code, or a function that uses any of the above pointer operators is marked as unsafe through the use of the unsafe keyword, as shown below:

public unsafe void Triple(int *pInt)



{


*pInt=(*pInt)*3;


}

All the above function does is triple the value passed to it. But notice that the address of the variable, containing the value to be tripled, is passed to the function. The function then does its work. Since the function is using the ‘*’ pointer operator, the function is marked as unsafe, since the memory is being directly manipulated.

However, there is a problem. If you recall from the discussion above, unsafe code is managed code, and hence, is being executed under CLR’s supervision. Now, the CLR is free to move the objects in memory. One plausible reason could be to reduce memory fragmentation. But in doing so, unknowingly and transparently to the programmer, the variable being pointed to could be get relocated to some other memory locations. So, if *pInt pointed to a variable which was at address 1001, and the CLR performs some memory relocation to reduce fragmentation, the variable which was earlier located at 1001 could, after relocation, be stored at memory location 2003. This is a catastrophe, since the pointer gets invalid as there’s nothing at memory location 1001 after relocation. Probably that’s one reason that the usage of pointers keeps a low profile in .Net. 

Fixing the pointers

Enter the fixed keyword. When used for a block of statements, it tells the CLR that the object in question cannot be relocated, and thus, it ends up pinning the object. Thus, when pointers are used in C#, then the fixed keyword is used pretty much often to prevent runtime invalid pointers. Let’s see how it works:

using system;



class CData


{


public int x;


}


class CProgram


{


unsafe static void SetVal(int *pInt)


{


*pInt=1979;


}


public unsafe static void Main()


{


CData d = new CData();


Console.WriteLine(“Previous value: {0}”,d.x);


fixed(int *p=&d.x)


{


SetVal(p);


}


Console.WriteLine(“New value: {0}”,d.x);


}


}



















All we do here is assign the address of field x of class CData to integer pointer p, within the fixed block. Now, while statements within the fixed block are executing, the pointer shall continue to point to the same memory location as the CLR has been instructed to pin the variable until the fixed block execution gets over. Once the fixed block is over, the object can be relocated in memory by the CLR.

So, that’s all there is to programming using pointers in C#. Just make sure that the block is unsafe and that the object being pointed is fixed. And you are ready to leverage your knowledge of pointers in C# too! The CD carries the code which exemplifies the concepts discussed.

Ending the C# odyssey

With this month’s issue, we are ending our six month-long C# tutorial which was meant to help you get started and work with the language. We hope that this series has been useful to you.

Kumar Gaurav Khanna runs www.wintoolzone.com

Advertisment