LanguagesFirst Impressions of C#: A Language Overview

First Impressions of C#: A Language Overview

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

"As a language, C# certainly has a lot of potential. Whether C# can overcome resistance from the Java community remains to be seen though.

"

C#, part of the new Microsoft .NET platform, bears all the hallmarks of a great language. Strikingly similar to Java, the language includes some of the best attributes of modern object-oriented languages, as well as adding a few new tricks of its own. In this second part of our series (see
First Impressions of C#: Java Killer or Java Wannabe?
,) I’ll cover some of the important new features of C#, along with offering a balanced view of its drawbacks.

Automatic Garbage Collection

One of the coolest features of Java is its support for automatic garbage collection (see
Understanding Automatic Garbage Collection
.) Rather than have to manually allocate memory (Do you remember the days of C and the

malloc
command?), you can simply create a new instance of an object. Once no references to the object exist, the memory can be safely reclaimed by the garbage collector. This helps save work for programmers and prevents memory leaks. Microsoft has taken this on board, and C# developers are free from memory management issues if they choose. Also, unlike finalizers in Java, destructors in C# are guaranteed to be called during garbage collection.

Support for Interfaces

Like Java, the C# language will support interfaces. Interfaces allow programmers to define a set of method signatures that must be implemented by a class. Classes that implement an interface can then be cast as that interface. For example, the Java

Thread
class accepts a

Runnable
instance in its constructor, allowing implementing classes to be identified as

Runnable
. Interfaces are an important feature that C++ lacked and will no doubt be very popular with C# developers.

Defining an interface in C# is no different to defining one in Java. However, the

implements
keyword from Java is not used — instead a class will extend an interface.


public interface Task
{
public void doTask();
}

public class Nothing : Task, SomeOtherClass
{
public void doTask()
{
System.Console.WriteLine ("Doing nothing….");
}
}

Listing 1. Interfaces in C# are extended, not implemented.

Type-safe Variables Automatically Initialized

If you remember the bad old days of C, you’ll remember that variables weren’t type-safe. If you had a pointer reference, you could treat that memory as an

int
, a

char
, or an entire data structure. Usually, you’d know what it pointed to, but without type-safe variables it was easy to make a mistake. Furthermore, the value of variables was not defined, so if you forgot to initialize variables you could run into problems. While most times, you could rely on the variable to be 0, if the memory region it was stored at had been used previously, the value could have been anything. This meant code would run fine sometimes, but in an unstable way at other times. Under C#, every variable is assigned a well-defined default value, so if you forget to initialize it, at least you’ll be guaranteed consistency.

Support for COM and the Windows API

C# includes support for the Component Object Model (COM) and the Windows API from the ground up. In fact, C# doesn’t even come with its own class library! Instead, C# relies on the same class libraries of other Microsoft-supported languages, such as C++ and Visual Basic. In this area, C# excels over Java. Even though native code can be accessed through J/Direct and the Java Native Interface, this is not an easy process. If C# makes accessing native code, and COM objects, as easy as in C++, it will have a clear advantage over Java.

Versioning

As projects become more complex, and team sizes grow, the need for versioning becomes significant. Developers modifying classes and adding new methods can cause all sorts of problems when method signatures collide or change. If a developer adds a new method to a base class, it may match the method signature in a subclass. Conversely, if a developer changes a method signature in a base class (changing parameters or method name), then subclasses no longer override it — causing a silent error that is extremely hard to detect.

To prevent these errors, C# requires method overriding to be explicit, so that compilers can generate warnings and errors that signal a problem. When overriding a method, the new override keyword is used. For example, consider the following code snippet, which illustrates its use


class NetworkServer
{
public virtual void start(int port)
{
// initialize server …..
}

public virtual void stop()
{
// shutdown server …..
}
}

class DebugServer : NetworkServer
{
public override void start(int port)
{
System.Console.WriteLine("DEBUG EVENT – Server initializing");

// initialize server
}

public override void stop()
{
System.Console.WriteLine("DEBUG EVENT – Server shutting down");

// shutdown server
}

}

Listing 2. Use of the override statement (highlighted in bold) for versioning

Delegates

Delegates are a replacement for the old function pointer of C++. Think of delegates as an object-oriented function pointer, that points to a specific object’s method. At runtime, the actual class of the object doesn’t need to be known, so objects of different classes can be substituted providing they adhere to the same method signature. You could iterate through a whole set of delegates, invoking them without caring which object they belong to. Of course, dynamic binding of methods (known as polymorphism) has been around in languages like Java and C++ from the very beginning, but delegates differ in that only a reference to the method of an object is being passed, not the object itself. This means you can limit access to other public member variables and methods and expose only the method to which a delegate is bound. When carefully used, this will be a really cool feature.

Flaws in the C# Language

So far, I’ve covered the strengths of C#. However, no evaluation of a language would be complete or fair without looking at its weaknesses, and there are quite a few. The following are some of the most important flaws:

  • use of pointers and "unsafe" code
  • few thread-specific language statements
  • lack of portability.

Use of Pointers and "Unsafe" Code

Microsoft was reluctant to ditch support for pointers. A purely object-oriented language, like Java, would be far safer than one that allows pointer manipulation and direct access to memory. As a partial concession, C# includes a new keyword, called

unsafe
, that denotes code that uses pointers.

Few Thread-specific Language Statements

While it’s certain that C# will support multithreading through the Windows API, it will place responsibility for writing thread-safe code on the programmer. Java includes the

synchronized
keyword, which prevents two threads from accessing a method or code block concurrently. A corresponding statement is offered by C#, called

lock
, but there aren’t any other thread-specific statements, such as the

volatile
modifier in Java.

Lack of Portability

One of Java’s chief claims to fame is cross-platform portability. While the folks at Redmond must have been worried that Java would topple their stranglehold over the operating system market, in the five years it’s been around that hasn’t happened. However, the numbers of Java developers have swelled, because of the ease in deploying software to multiple platforms. An attempt has been made by Microsoft to create a semi-portable language, in the form of C#.

Microsoft has created what it terms the "Common Language Subset" (CLS), which allows CLS-compliant languages and class libraries. That means, in theory, that a CLS-compliant interpreter written for Unix could run C# code, just like Java bytecode is executed inside a JVM. However, with the reliance of C# on the COM architecture, C# applications are mostly limited to running on the Windows .NET platform — particularly if they take advantage of Windows-specific features. While it may be possible to port or translate "generic" code that doesn’t access native features, just like in Visual J++ 6.0 developers will find it very tempting to write for only Windows machines. Java, on the other hand, lends itself to writing portable code, and provides only limited access to native code via the Java Native Interface (JNI).

Summary

As a language, C# certainly has a lot of potential. For existing C++ developers, there are some great language features that, until now, were enjoyed only by those in the Java camp. For existing Java developers, of course, there’s the prospect of writing fast applications that harness all the potential of the Windows API. Whether or not C# can overcome resistance from the Java community and become a real threat remains to be seen though. The likely scenario is that Windows C++ developers and some Java coders will migrate to C#, some will use both, and most Java developers will remain loyal. Java’s days aren’t numbered, but neither are Microsoft C#’s.

About the Author

David Reilly is a software engineer and freelance technical writer living in Australia. A Sun Certified Java 1.1 Programmer, his research interests include the Java programming language, networking & distributed systems, and software agents. He can be reached by e-mail at java@davidreilly.com or via his personal Website.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories