The C# language is an object-oriented language that is aimed at enabling programmers to quickly build a wide range of applications for the Microsoft .NET platform. The goal of C# and the .NET platform is to shorten development time by freeing the developer from worrying about several low level plumbing issues such as memory management, type safety issues, building low level libraries, array boundschecking , etc. thus allowing developers to actually spend their time and energy working on their application and business logic instead. As a Java developer the previous sentence could be described as "a short description of the Java language and platform" if the words C# and the .NET platform were replaced with words Java and the Java platform.

What follows is an overview of similarities and differences between the language features and libraries of the C# and Java programming languages based on my experience using both languages. All code snippets below were tested on Microsoft's .NET Framework version 2.0 for C# snippets and Java™ Platform, Standard Edition version 6 for the Java snippets.

In situations where value types need to be treated as objects, the .NET and Java runtimes automatically converts value types to objects by wrapping them within a heap-allocated reference type in a process called boxing . The process of automatically convert an object to its corresponding value type such as converting an instance of java.lang.Integer to an int is known as unboxing . Below are examples of various situations where boxing occurs in both runtimes.

Instance and static variables can be initialized at their point of definition in both C# and Java. If the member variable is an instance variable, then initialization occurs just before the constructor is called. Static members are initialized sometime before the first usage of the member and before the first creation of an instance of the class. It is also possible to specify a block of code that should run before the class is used either via creation of an instance variable or invocation of a static method. These code blocks are called are called static constructors in C# and static initialization blocks in Java. Static constructors are invoked before the first invocation of a static method in the class and before the first time an instance of the class is created.

Both Java and C# provide mechanisms to specify that a class should be the last one in an inheritance hierarchy and cannot be used as a base class. In Java this is done by preceding the class declaration with the final keyword while in C# this is done by preceding the class declaration with the sealed keyword. Below are examples of classes that cannot be extended in either language

C# has a System.String class which is analogous to the java.lang.String class. Both classes are immutable meaning that the values of the strings cannot be changed once the strings have been created. In both instances methods that appear to modify the actual content of a string actually create a new string to return, leaving the original string unchanged. Thus the following C# and Java code does not modify the string in either case

C#, like Java, supports the concept of an interface which is akin to a pure abstract class. Similarly C# and Java both allow only single inheritance of classes but multiple inheritance (or implementation) of interfaces.

Just like Java and unlike C++, methods in C# have to be part of a class either as member or static methods.

In languages like C and C++, each subarray of a multidimensional array must have the same dimensions. In Java and C# arrays do not have to be uniform because jagged arrays can be created as one-dimensional arrays of arrays. In a jagged array the contents of the array are arrays which may hold instances of a type or references to other arrays. For this reason the rows and columns in a jagged array need not have uniform length as can be seen from the following code snippet:

In Java objects are created on the heap using the new keyword. Most classes in C# are created on the heap by using the new keyword. Also just as the JVM manages the destruction of objects so also does the CLR via a Mark and Compact garbage collection algorithm NOTE: C# also supports stack-based classes, called value types, which are discussed further below.

Just like Java is typically compiled to Java byte code which then runs in managed execution environment (the Java Virtual Machine or JVM) so also is C# code compiled to an Intermediate Language (IL) which then runs in the Common Language Runtime (CLR). Both platforms support native compilation via Just In Time compilers . NOTE: While the Java platform supports interpretation of byte code or byte code being JITed then run natively, the .NET platform only supports native execution of C# code because the IL code is always natively compiled before running.

There are a large number of syntactic similarities between Java and C#, similarly almost every Java keyword has a C# equivalent except for a few like transient, throws and strictfp. Below is a table of Java and C# keywords with the Java keywords in red while the equivalent C# keywords are in blue.

Just like Java, C# has a single rooted class hierarchy where all classes in C# are subclasses of System.Object the same way all Java classes are subclasses of java.lang.Object . The methods of the two languages' Object classes share some similarities (e.g. System.Object's ToString() to java.lang.Object's toString()) and differences ( System.Object does not have analogs to wait(), notify() or notifyAll() in java.lang.Object ). NOTE: In C#, the object class can either be written as object or Object. The lower case "object" is a C# keyword which is replaced with the class name "System.Object" during compilation.

Enums are used to create and group together a list of user defined named constants. Although on the surface the enumerated types in C# and Java seem quite similar there are some significant differences in the implementation of enumerated types in both languages. In Java, enumerated types are a full fledged class which means they are typesafe and can be extended by adding methods, fields or even implementing interfaces. Whereas in C#, an enumerated type is simply syntactic sugar around an integral type (typically an int ) meaning they cannot be extended and are not typesafe.

As in C# it is possible to access the annotations on a module, class, method or field via reflection . However a key difference between C# attributes and Java annotations is that one can create meta-annotations (i.e. annotations on annotations) in Java but can not do the same in C#. Developers can create their own custom annotations by creating an annotation type which is similar to an interface except that the keyword @interface is used to define it. What follows is an example of using an attribute to provide information about the author of a class then using reflection to access that information.

Java annotations provide a way to add annotations (i.e. metadata) to an package, type, method, parameter, member or local variable. There are only three built-in annotations provided in the Java language which are listed below.

It is possible to access the attributes of a module, class, method or field via reflection . This is particularly useful for seeing if a class supports certain behavior at runtime or for extracting metadata about a class for usage by others. Developers can create their own custom attributes by subclassing the System.Attribute class. What follows is an example of using an attribute to provide information about the author of a class then using reflection to access that information.

C# attributes provide a way to add annotations (i.e. metadata) to a module, type, method, parameter or member variable. Below are descriptions of a few attributes that are intrinsic to .NET and how they are used to extend the capabilities of the C#.

Metadata annotations provide a powerful way to extend the capabilities of a programming language and the language runtime. These annotations can be directives that request the runtime to perform certain additional tasks, provide extra information about an item or extend the abilities of a type. Metadata annotations are common in a number of programming environments including Microsoft's COM and the Linux kernel.

In C#, the keywords foreach and in are used when creating the for-each loop while in Java the keyword for and the operator : are used.

The for-each loop is an iteration construct that is popular in a number of scripting languages (e.g. Perl, PHP, Tcl/Tk), build tools (GNU Make) and function libraries (e.g. for_each in <algorithm> in C++). The for-each loop is a less verbose way to iterate through arrays or classes that implement the the System.Collections.IEnumerable interface in C# or the java.lang.Iterable interface in Java.

C# also includes the default operator which returns the default value for a type. The default value for reference types is null , and the default value for value types (such as integers, enum, and structures) is a zero whitewash (filling the structure with zeros). This operator is very useful when combined with generics. The following code sample excercises the functionality of this operator.

Both C# and Java provide mechanisms for specifying constraints on generic types. In C# there are three types of constraints that can be applied to generic types

In certain cases, one may need create a method that can operate on data structures containing any type as opposed to those that contain a specific type (e.g. a method to print all the objects in a data structure) while still taking advantage of the benefits of strong typing in generics. The mechanism for specifying this in C# is via a feature called generic type inferencing while in Java this is done using wildcard types . The following code samples show how both approaches lead to the same result.

In C#, there is explicit support for generics in the .NET runtime's instruction language (IL). When the generic type is compiled, the generated IL contains place holders for specific types. At runtime, when an initial reference is made to a generic type (e.g. List<int> ) the system looks to see if anyone already asked for the type or not. If the type has been previously requested, then the previously generated specific type is returned. If not, the JIT compiler instantiates a new type by replacing the generic type parameters in the IL with the specific type (e.g. replacing List<T> with List<int> ). It should be noted that if the requested type is a reference type as opposed to a value type then the generic type parameter is replaced with Object . However there is no casting done internally by the .NET runtime when accessing the type.

Although similar in concept to templates in C++, the Generics feature in C# and Java is not implemented similarly. In Java, the generic functionality is implemented using type erasure . Specifically the generic type information is present only at compile time, after which it is erased by the compiler and all the type declarations are replaced with Object . The compiler then automatically inserts casts in the right places. The reason for this approach is that it provides total interoperability between generic code and legacy code that doesn't support generics. The main problem with type erasure is that the generic type information is not available at run time via reflection or run time type identification. Another consequence of this approach is that generic data structures types must always be declared using objects and not primitive types. Thus one must create Stack<Integer> instead of Stack<int> when working integers.

The following code sample shows how one would calculate the sum of all the integers in a collection using generics and using a collection of Objects so that both approaches can be compared.

Both C# and Java provide a mechanism for creating strongly typed data structures without knowing the specific types at compile time. Prior to the existence of the Generics feature set, this capability was achieved by specifying the type of the objects within the data structure as Object then casting to specific types at runtime. This technique had several drawbacks including lack of type safety, poor performance and code bloat.

In C and C++ it is possible to specify that a function takes a variable number of arguments. This functionality is used extensively in the printf and scanf family of functions. Both C# and Java allow one to define a parameter that indicates that a variable number of arguments are accepted by a method. In C#, the mechanism for specifying that a method accepts a variable number of arguments is by using the params keyword as a qualifier to the last argument to the method which should be an array. In Java, the same effect is achieved by appending the string "..." to the typename of the last argument to the method.

Both languages also provide a way to call a constructor from another which allows one to reduce the amount of code duplication that can occur in constructors. This practice is typically called constructor chaining.

C# and Java automatically call base class constructors, and both provide a way to call the constructor of the base class with specific parameters. Similarly both languages enforce that the call to the base class constructor occurs before any initializations in the derived constructor which prevents the derived constructor from using members that are yet to be initialized. The C# syntax for calling the base class constructor is reminiscent of the C++ initializer list syntax.

NOTE: The Java language also supports having final parameters to a method. This functionality is non-existent in C#. The primary use of final parameters is to allow arguments to a method to be accessible from within inner classes declared in the method body.

Unlike C++, it is not possible to specify an immutable class via language constructs in either C# or Java. Neither is it possible to create a reference through which it's impossible to modify a mutable object.

To declare constants in C# the const keyword is used for compile time constants while the readonly keyword is used for runtime constants. The semantics of constant primitives and object references in C# is the same as in Java.

To declare constants in Java the final keyword is used. Final variables can be set either at compile time or run time. In Java, when the final is used on a primitive it makes the value of the primitive immutable while when used on object references it makes the reference constant meaning that the reference can only point to only one object during its lifetime. Final members can be left uninitialized when declared but then must be defined in the constructor.

Sometimes there is a need to obtain the metadata of a specific class encapsulated as an object. This object is the java.lang.Class object in Java and the System.Type object in C#. To retrieve this metadata class from an instance of the target class, the getClass() method is used in Java while the GetType() method is used in C#. If the name of the class is known at compile time then one can avoid creating an instance of the class just to obtain the metadata class by doing the following

One might notice from the above code samples that there is slightly more granularity in the C# Reflection API than the Java Reflection API as can be seen by the fact that C# has a ParameterInfo class which contains metadata about the parameters of a Method while Java uses Class objects for that which lose some information such as the name of the parameter.

NOTE: The default accessibility of a C# field or method when no access modifier is specified is private while in Java it is protected (except that derived classes from outside the package cannot inherit the field).

Below is a table mapping C# access modifiers to Java's. C++ fans who were disappointed when Sun changed the semantics of the protected keyword in Java 2 will be happy to note that the C# protected keyword has the same semantics as the C++ version. This means that a protected member can only be accessed by member methods in that class or member methods in derived classes but is inaccessible to any other classes. The internal modifier means that the member can be accessed from other classes in the same assembly as the class. The internal protected modifier means that a member can be accessed from classes that are in the same assembly or from derived classes.

Both C# and Java support the concept of synchronized methods. Whenever a synchronized method is called, the thread that called the method locks the object that contains the method. Thus other threads cannot call a synchronized method on the same object until the object is unlocked by the first thread when it finishes executing the synchronized method. Synchronized methods are marked in Java by using the synchronized keyword while in C# it is done by annotating the method with the [MethodImpl(MethodImplOptions.Synchronized)] attribute. Examples of synchronized methods are shown below

The syntax and semantics for constructors in C# is identical to that in Java. C# also has the concept of destructors which use syntax similar to C++ destructor syntax but have the mostly the same semantics as Java finalizers. Although finalizers exist doing work within them is not encouraged for a number of reasons including the fact that there is no way to control the order of finalization which can lead to interesting problems if objects that hold references to each other are finalized out of order. Finalization also causes more overhead because objects with finalizers aren't removed after the garbage collection thread runs but instead are eliminated after the finalization thread runs which means they have to be maintained in the system longer than objects without finalizers. Below are equivalent examples in C# and Java.

A C# namespace is a way to group a collection of classes and is used in a manner similar to Java's package construct. Users of C++ will notice the similarities between the C# namespace syntax and that in C++. In Java, the package names dictate the directory structure of source files in an application whereas in C# namespaces do not dictate the physical layout of source files in directories only their logical structure. Examples below:

Since C# is aimed at transitioning C++ developers the above syntax is understandable although Java developers may pine for the Java syntax especially since it is clear from looking at the class declaration in the Java version whether the class is subclassing a class or simply implementing an interface while it isn't in the C# version without intimate knowledge of all the classes involved. Although it should be noted that in .NET naming conventions, interface names have an upper-case "I" prepended to their names (as in IClonable), so this isn't an issue for programs that conform to standard naming conventions.

So in Java's favor, one doesn't have to recompile to change which main is used by the application while a recompile is needed in a C# application. However, On the other hand, Java doesn't support conditional compilation, so the main method will be part of even your released classes.

It is typically recommended that one creates a main method for each class in an application to test the functionality of that class besides whatever main method actually drives the application. For instance it is possible to have two classes, A and B, which both contain main methods. In Java, since a class is the unit of compilation then all one has to do is invoke the specific class one wants run via the command line to run its main method. In C# one can get the same effect by compiling the application with the /main switch to specify which main should be used as the starting point of the application when the executable is created. Using test mains in combination with conditional compilation via preprocessor directives is a powerful testing technique.

Nested classes In Java and C# it is possible to nest class declarations within each other. In Java there are two kinds of nested classes; non-static nested classes also known as inner classes and static nested classes. A Java inner class can be considered as a one-to-one relationship between the inner class and its enclosing class where for each instance of the enclosing class there exists a corresponding instance of the inner class that has access to the enclosing class's instance variables and contains no static methods. On the other hand a Java static nested class is a similar to nesting a class decaration within another where the nested class has access to the static members and methods of the enclosing class. C# has the equivalent of Java's static nested classes but has nothing analogous to Java's inner classes. The following nested class declarations below are equivalent C# Code public class Car{ private Engine engine; private class Engine{ string make; } } Java Code public class Car{ private Engine engine; private static class Engine{ String make; } } NOTE: In Java a nested class can be declared in any block of code including methods, this is not the case in C#. The ability to create nested classes in methods in Java may seem unnecessary but combined with anonymous inner classes can provide a means of creating powerful design patterns.

Threads and Volatile Members A thread is a sequential flow of control within a program. A program or process can have multiple threads running concurrently all of which may share data or run independently while performing tasks. Threads are powerful in that they allow a developer to perform multiple tasks at once in a single program or process. Advantages of threads include exploiting parallelism in multiprocessor architectures, reducing execution time by being able to perform tasks while waiting on a blocking system calls (such as printing or other I/O), and avoiding freezing in GUI applications. Java threads are created by subclassing the java.lang.Thread class and overriding its run() method or by implementing the java.lang.Runnable interface and implementing the run() method. Whereas in C#, one creates a thread by creating a new System.Threading.Thread object and passing it a System.Threading.ThreadStart delegate which is initialized with the method that is to be run as a thread. Thus, in Java a method that shall run in a multithreaded context is designed up front specifically with that in mind. On the other hand, in C# any method can be passed to a ThreadStart object and run in a multithreaded scenario. In Java, every class inherits the wait(), notify() and notifyAll() from java.lang.Object which are used for thread operations. The equivalent methods in C# are the Wait(), Pulse() and PulseAll() methods in the System.Threading.Monitor class. The example below shows a scenario where worker threads are dispatched in a specific order and must be processed in the same order upon return. Due to the non-deterministic nature of threads, on some runs the threads finish working in the order they were dispatched in and in other runs they appear out of order and thus each thread must wait until its turn comes up. C# Code using System; using System.Threading; using System.Collections; public class WorkerThread{ private int idNumber; private static int num_threads_made = 1; private ThreadSample owner; public WorkerThread(ThreadSample owner){ idNumber = num_threads_made; num_threads_made++; this.owner = owner; }/* WorkerThread() */ //sleeps for a random amount of time to simulate working on a task public void PerformTask(){ Random r = new Random((int) DateTime.Now.Ticks); int timeout = (int) r.Next() % 1000; if(timeout < 0) timeout *= -1; //Console.WriteLine(idNumber + ":A"); try{ Thread.Sleep(timeout); } catch (ThreadInterruptedException e){ Console.WriteLine("Thread #" + idNumber + " interrupted"); } //Console.WriteLine(idNumber + ":B"); owner.workCompleted(this); }/* performTask() */ public int getIDNumber() {return idNumber;} } // WorkerThread public class ThreadSample { private static Mutex m = new Mutex(); private ArrayList threadOrderList = new ArrayList(); private int NextInLine(){ return (int) threadOrderList[0]; } private void RemoveNextInLine(){ threadOrderList.RemoveAt(0); //all threads have shown up if(threadOrderList.Count == 0) Environment.Exit(0); } public void workCompleted(WorkerThread worker){ try{ lock(this){ while(worker.getIDNumber() != NextInLine()){ try { //wait for some other thread to finish working Console.WriteLine ("Thread #" + worker.getIDNumber() + " is waiting for Thread #" + NextInLine() + " to show up."); Monitor.Wait(this, Timeout.Infinite); } catch (ThreadInterruptedException e) {} }//while Console.WriteLine("Thread #" + worker.getIDNumber() + " is home free"); //remove this ID number from the list of threads yet to be seen RemoveNextInLine(); //tell the other threads to resume Monitor.PulseAll(this); } }catch(SynchronizationLockException){Console.WriteLine("SynchronizationLockException occurred");} } public static void Main(String[] args){ ThreadSample ts = new ThreadSample(); /* Launch 25 threads */ for(int i=1; i <= 25; i++){ WorkerThread wt = new WorkerThread(ts); ts.threadOrderList.Add(i); Thread t = new Thread(new ThreadStart(wt.PerformTask)); t.Start(); } Thread.Sleep(3600000); //wait for it all to end }/* main(String[]) */ }//ThreadSample Java Code import java.util.*; class WorkerThread extends Thread{ private Integer idNumber; private static int num_threads_made = 1; private ThreadSample owner; public WorkerThread(ThreadSample owner){ super("Thread #" + num_threads_made); idNumber = new Integer(num_threads_made); num_threads_made++; this.owner = owner; start(); //calls run and starts the thread. }/* WorkerThread() */ //sleeps for a random amount of time to simulate working on a task public void run(){ Random r = new Random(System.currentTimeMillis()); int timeout = r.nextInt() % 1000; if(timeout < 0) timeout *= -1 ; try{ Thread.sleep(timeout); } catch (InterruptedException e){ System.out.println("Thread #" + idNumber + " interrupted"); } owner.workCompleted(this); }/* run() */ public Integer getIDNumber() {return idNumber;} } // WorkerThread public class ThreadSample{ private Vector threadOrderList = new Vector(); private Integer nextInLine(){ return (Integer) threadOrderList.firstElement(); } private void removeNextInLine(){ threadOrderList.removeElementAt(0); //all threads have shown up if(threadOrderList.isEmpty()) System.exit(0); } public synchronized void workCompleted(WorkerThread worker){ while(worker.getIDNumber().equals(nextInLine())==false){ try { //wait for some other thread to finish working System.out.println (Thread.currentThread().getName() + " is waiting for Thread #" + nextInLine() + " to show up."); wait(); } catch (InterruptedException e) {} }//while System.out.println("Thread #" + worker.getIDNumber() + " is home free"); //remove this ID number from the list of threads yet to be seen removeNextInLine(); //tell the other threads to resume notifyAll(); } public static void main(String[] args) throws InterruptedException{ ThreadSample ts = new ThreadSample(); /* Launch 25 threads */ for(int i=1; i <= 25; i++){ new WorkerThread(ts); ts.threadOrderList.add(new Integer(i)); } Thread.sleep(3600000); //wait for it all to end }/* main(String[]) */ }//ThreadSample In many situations one cannot guarantee that the order of execution of a program will be the same as that in the source code. Reasons for the unexpected ordering of program execution include compiler optimizations that reorder statements or mulitiprocessor systems that fail to store variables in global memory amongst others. To work around this, both C# and Java have the concept of the volatile keyword which is used to tell the language runtime that reordering instructions related to accessing such fields is prohibited. There are major differences in the semantics of volatile in Java and C# which are illustrated in the example below taken from The "Double-Checked Locking is Broken" Declaration C# Code /* Used to lazily instantiate a singleton class */ /* WORKS AS EXPECTED */ class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { lock(this) { if (helper == null) helper = new Helper(); } } return helper; } } Java Code /* Used to lazily instantiate a singleton class */ /* BROKEN UNDER CURRENT SEMANTICS FOR VOLATILE */ class Foo { private volatile Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } } return helper; } } Although the above code snippets seem identical save for the substitution of the synchronized keyword with the lock keyword, the Java version is not guaranteed to work on all JVMs. Currently the Java Memory Model does not prevent reordering of writes to volatile variables with writes to other variables so it is possible that the new object is constructed before the helper reference is made to point at the newly created object meaning that two objects are created. Also it is possible that the helper reference is made to point at a block of memory while the object is still being created meaning that a reference to an incomplete object will be returned. In C#, the semantics of volatile prevent such problems from occurring because reads and writes cannot be moved backward or forward across a volatile write. Also in C#, being marked as volatile also prevents the Just In Time compiler from placing the variable in a register and also ensures that the variable is stored in global memory on multiprocessor systems. For more information on the problems with the Java Memory Model and Double-Checked Locking, see the Double-checked locking: Clever, but broken article on Javaworld.

Operator Overloading Operator overloading allows standard operators in a language to be given new semantics when applied in the context of a particular class or type. Operator overloading can be used to simplify the syntax of certain operations especially when they are performed very often, such as string concatenation in Java or interactions with iterators and collections in the C++ Standard Template Library. Operator overloading is a point of contention for many developers due to the fact that it provides a lot of flexibility and power which makes it prone to abuse. There is a tendency for developers to use it poorly by doings like overloading operators in an unintuitive manner (e.g. overloading ++ and -- to connect and disconnect from the network) , overloading operators in a manner inconsistent with their typical use (e.g. overloading [ ] to return a copy of an object at a particular index in a collection instead of a reference to the actual object) or overloading some operators and not others (e.g. overloading < but not > ). Overloading operators tends to be most useful when the class lends itself intuitively to using that operator. Examples of situations that intuitively suggest that operator overloading would be beneficial are overloading [ ] for use with collections, overloading + and * for use with matrices, overloading mathematical operators for use with complex numbers, and overloading the == and != operators for classes that have some means to measure equality. Below is an example that shows how operator overloading works in C#. NOTE: Unlike C++, C# does not allow the overloading of the following operators; new , ( ) , || , && , = , or any variations of compound assignments such as += , -= , etc. However, compound assignment operators will call overloaded operators, for instance, += would call overloaded +. C# Code using System; class OverloadedNumber{ private int value; public OverloadedNumber(int value){ this.value = value; } public override string ToString(){ return value.ToString(); } public static OverloadedNumber operator -(OverloadedNumber number){ return new OverloadedNumber(-number.value); } public static OverloadedNumber operator +(OverloadedNumber number1, OverloadedNumber number2){ return new OverloadedNumber(number1.value + number2.value); } public static OverloadedNumber operator ++(OverloadedNumber number){ return new OverloadedNumber(number.value + 1); } } public class OperatorOverloadingTest { public static void Main(string[] args){ OverloadedNumber number1 = new OverloadedNumber(12); OverloadedNumber number2 = new OverloadedNumber(125); Console.WriteLine("Increment: {0}", ++number1); Console.WriteLine("Addition: {0}", number1 + number2); } } // OperatorOverloadingTest

switch Statment There are two major differences between the switch statement in C# versus that in Java. In C#, switch statements support the use of string literals and do not allow fall-through unless the label contains no statements. Fall-throughs are explicitly disallowed because they are a leading cause of hard-to-find bugs in software. C# Code switch(foo){ case "A": Console.WriteLine("A seen"); break; case "B": case "C": Console.WriteLine("B or C seen"); break; /* ERROR: Won't compile due to fall-through at case "D" */ case "D": Console.WriteLine("D seen"); case "E": Console.WriteLine("E seen"); break; }

Assemblies C# assemblies share a lot in common with Java JAR files. An assembly is the fundamental unit of code packaging in the .NET environment. Assemblies are self contained and typically contain the intermediate code from compiling classes, metadata about the classes, and any other files needed by the packaged code to perform its task. Since assemblies are the fundamental unit of code packaging, several actions related to interacting with types must be done at the assembly level. For instance, granting of security permissions, code deployment, and versioning are done at the assembly level. Java JAR files perform a similar task in Java with most differences being in the implementation. Assemblies are usually stored as EXEs or DLLs while JAR files are stored in the ZIP file format.

Collections A number of popular programming languages contain a collections framework which typically consists of a number of data structures for holding multiple objects as well as algorithms for manipulating the objects within the aforementioned data structures. The primary advantage of a collections framework is that it frees developers from having to write data structures and sort algorithms every time one is needed and instead frees them up to work on the actual application logic. A secondary benefit is that collections frameworks lead to consistency across projects which means the learning curve for new developers using applications that use a collections framework is less steep when compared to a situation where one was not used. The C# collections framework consists of the classes in the System.Collections and the System.Collections.Generic namespaces. The Systems.Collections namespace contains interfaces and abstract classes that represent abstract data types such as IList, IEnumerable, IDictionary, ICollection, and CollectionBase which enable developers to manipulate data structures independently of how they are actually implemented as long as the data structures inherit from the abstract data types. The System.Collections namespace also contains some concrete implementations of data structures such as ArrayList, Stack, Queue, HashTable and SortedList. All four of the concrete data structure implementations enable one to obtain synchronized wrappers to the collection which allows for access in a thread-safe manner. The System.Collections.Generic namespace has generic implementations of the key data structures in the System.Collections namespace including generic List<T>, Stack<T>,Queue<T>, Dictionary<K,T> and SortedDictionary<K,T> classes . The Java collections framework consists of a large number of the classes and interfaces in the java.util package. Instead of having a separate namespace for generic collections, the collections in the java.util package have been retrofitted to support generics. The Java collection framework is similar to that in C# except for the fact that it can be considered a superset of the C# collection framework since it contains a number of extra features. The Java collection framework contains data structures that are missing from those in C# such as sets and linked lists. Also the Java collections framework not only has methods that enable one to access unsafe collections in a thread safe manner but contains thread-safe versions of most of the data structures as well. Finally, the Java collections framework has a number of algorithms for manipulating the elements within the data structures including algorithms that can do the following; find the largest element based on some Comparator, find the smallest element, find sublists within a list, reverse the contents of a list, shuffle the contents of a list, creates immutable versions of a colection, performs sorts, and binary searches. At the current time, the Java collections framework is more sophisticated than that available in .NET via C#.

goto (no longer considered harmful) Unlike Java, C# contains the goto statement which can be used to jump directly from a point in the code to a label. Although much derided, gotos can be used in certain situations to reduce code duplication while enhancing readability. A secondary usage of the goto statement is the ability to mimic resumeable exceptions like those in Smalltalk, as long as the exception thrown does not cross method boundaries. NOTE: In C#, one cannot jump into a statement block using the goto statement; C# Code using System; using System.Net.Sockets; class GotoSample{ public static void Main(string[] args){ int num_tries = 0; retry: try{ num_tries++; Console.WriteLine("Attempting to connect to network. Number of tries =" + num_tries); //Attempt to connect to a network times out //or some some other network connection error that //can be recovered from throw new SocketException(); }catch(SocketException){ if(num_tries < 5) goto retry; } }/* Main(string[]) */ }//GotoSample

Virtual Methods (and final ones too) One of the tenets of object oriented programming is polymorphism. Polymorphism enables one to interact with members of a type hierarchy as generic types instead of dealing with specific types. The means of implementing polymorphism typically involves having methods in a base class that may be overidden by derived classes. These methods can be invoked even though the client has a reference to a base class type which points to an object of the derived class. Such methods are bound at runtime instead of being bound during compilation and are typically called virtual methods. In Java all methods are virtual methods while in C#, as in C++, one must explicitly state which methods one wants to be virtual since by default they are not. To mark a method as virtual in C#, one uses the virtual keyword. Also, implementers of a child class can decide to either explicitly override the virtual method by using the override keyword or explicitly choose not to by using the new keyword instead. By default, in C#, the behavior of methods in a derived class that have the same signature as those in the base class is as if they were declared with the new keyword. It is possible to mark methods as final in Java which means that the method cannot be overridden by derived classes. In C# this can be done by not marking the method as virtual . The major difference is that in C#, the class can still define the method but the base class version is the one that will be called if the object is used via a base class reference. Java disallows the derived class from containing a method that has the same signature as the final base class method. Below are examples that show the differences in virtual methods in both languages. C# Code using System; public class Parent{ public void DoStuff(string str){ Console.WriteLine("In Parent.DoStuff: " + str); } } public class Child: Parent{ public void DoStuff(int n){ Console.WriteLine("In Child.DoStuff: " + n); } public void DoStuff(string str){ Console.WriteLine("In Child.DoStuff: " + str); } } public class VirtualTest{ public static void Main(string[] args){ Child ch = new Child(); ch.DoStuff(100); ch.DoStuff("Test"); ((Parent) ch).DoStuff("Second Test"); } }//VirtualTest OUTPUT: In Child.DoStuff: 100 In Child.DoStuff: Test In Parent.DoStuff: Second Test Java Code class Parent{ public void DoStuff(String str){ System.out.println("In Parent.DoStuff: " + str); } } class Child extends Parent{ public void DoStuff(int n){ System.out.println("In Child.DoStuff: " + n); } public void DoStuff(String str){ System.out.println("In Child.DoStuff: " + str); } } public class VirtualTest{ public static void main(String[] args){ Child ch = new Child(); ch.DoStuff(100); ch.DoStuff("Test"); ((Parent) ch).DoStuff("Second Test"); } }//VirtualTest OUTPUT: In Child.DoStuff: 100 In Child.DoStuff: Test In Child.DoStuff: Second Test The C# example can be made to produce the same output as the Java example by marking the DoStuff(string) method in the Parent class as virtual and marking the DoStuff(string) method in the Child class with the override keyword. C# Code using System; public class Parent{ public virtual void DoStuff(string str){ Console.WriteLine("In Parent.DoStuff: " + str); } } public class Child: Parent{ public void DoStuff(int n){ Console.WriteLine("In Child.DoStuff: " + n); } public override void DoStuff(string str){ Console.WriteLine("In Child.DoStuff: " + str); } } public class VirtualTest{ public static void Main(string[] args){ Child ch = new Child(); ch.DoStuff(100); ch.DoStuff("Test"); ((Parent) ch).DoStuff("Second Test"); } }//VirtualTest OUTPUT: In Child.DoStuff: 100 In Child.DoStuff: Test In Child.DoStuff: Second Test The above example can be made to produce the original results by altering the signature of the DoStuff(string) method in the Child class to public new void DoStuff(string str) which states that although the DoStuff method is virtual in the base class, the child class would like to treat it as a non-virtual method.





File I/O Both languages support performing I/O via Stream classes. The examples below copy the contents of a file named "input.txt" to another called "output.txt". C# Code using System; using System.IO; public class FileIOTest { public static void Main(string[] args){ FileStream inputFile = new FileStream("input.txt", FileMode.Open); FileStream outputFile = new FileStream("output.txt", FileMode.Open); StreamReader sr = new StreamReader(inputFile); StreamWriter sw = new StreamWriter(outputFile); String str; while((str = sr.ReadLine())!= null) sw.Write(str); sr.Close(); sw.Close(); } }//FileIOTest Java Code import java.io.*; public class FileIO{ public static void main(String[] args) throws IOException { File inputFile = new File("input.txt"); File outputFile = new File("output.txt"); FileReader in = new FileReader(inputFile); BufferedReader br = new BufferedReader(in); FileWriter out = new FileWriter(outputFile); BufferedWriter bw = new BufferedWriter(out); String str; while((str = br.readLine())!= null) bw.write(str); br.close(); bw.close(); } }//FileIOTest

Object Serialization Object Persistence also known as Serialization is the ability to read and write objects via a stream such as a file or network socket. Object Persistence is useful in situations where the state of an object must be retained across invocations of a program. Usually in such cases simply storing data in a flat file is insufficient yet using a Database Management System (DBMS) is overkill. Serialization is also useful as a means of transferring the representation of a class in an automatic and fairly seamless manner. Serializable objects in C# are annotated with the [Serializable] attribute. The [NonSerialized] attribute is used to annote members of a C# class that should not be serialized by the runtime. Such fields are usually calculated or temporary values that have no meaning when saved. C# provides two formats for serializing classes; either as XML or in a binary format, the former is more readable by humans and applications while the latter is more efficient. One can also define custom ways an object is serialized if the standard ways are insufficient by implementing the ISerializable interface. In Java, serializable objects are those that implement the Serializable interface while the transient keyword is used to mark members of a Java class as ones not to be serialized. By default Java supports serializing objects to a binary format but does provide a way of overriding the standard serialization process. Objects that plan to override default serializations can implement methods with the following signatures private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException; private void writeObject(java.io.ObjectOutputStream stream) throws IOException Since the above methods are private there is no interface that can be implemented to indicate that a Java class supports custom serialization using readObject and writeObject. For classes that need publicly accessible methods for custom serialization there exists the java.io.Externalizable interface which specifies the readExternal() and writeExternal() for use in customizing how an object is read and written to a stream.



C# Code using System; using System.IO; using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap; [Serializable] class SerializeTest{ [NonSerialized] private int x; private int y; public SerializeTest(int a, int b){ x = a; y = b; } public override String ToString(){ return "{x=" + x + ", y=" + y + "}"; } public static void Main(String[] args){ SerializeTest st = new SerializeTest(66, 61); Console.WriteLine("Before Binary Write := " + st); Console.WriteLine("

Writing SerializeTest object to disk"); Stream output = File.Create("serialized.bin"); BinaryFormatter bwrite = new BinaryFormatter(); bwrite.Serialize(output, st); output.Close(); Console.WriteLine("

Reading SerializeTest object from disk

"); Stream input = File.OpenRead("serialized.bin"); BinaryFormatter bread = new BinaryFormatter(); SerializeTest fromdisk = (SerializeTest)bread.Deserialize(input); input.Close(); /* x will be 0 because it won't be read from disk since non-serialized */ Console.WriteLine("After Binary Read := " + fromdisk); st = new SerializeTest(19, 99); Console.WriteLine("



Before SOAP(XML) Serialization := " + st); Console.WriteLine("

Writing SerializeTest object to disk"); output = File.Create("serialized.xml"); SoapFormatter swrite = new SoapFormatter(); swrite.Serialize(output, st); output.Close(); Console.WriteLine("

Reading SerializeTest object from disk

"); input = File.OpenRead("serialized.xml"); SoapFormatter sread = new SoapFormatter(); fromdisk = (SerializeTest)sread.Deserialize(input); input.Close(); /* x will be 0 because it won't be read from disk since non-serialized */ Console.WriteLine("After SOAP(XML) Serialization := " + fromdisk); Console.WriteLine("



Printing XML Representation of Object"); XmlDocument doc = new XmlDocument(); doc.Load("serialized.xml"); Console.WriteLine(doc.OuterXml); } } Java Code import java.io.*; class SerializeTest implements Serializable{ transient int x; private int y; public SerializeTest(int a, int b){ x = a; y = b; } public String toString(){ return "{x=" + x + ", y=" + y + "}"; } public static void main(String[] args) throws Exception{ SerializeTest st = new SerializeTest(66, 61); System.out.println("Before Write := " + st); System.out.println("

Writing SerializeTest object to disk"); FileOutputStream out = new FileOutputStream("serialized.txt"); ObjectOutputStream so = new ObjectOutputStream(out); so.writeObject(st); so.flush(); System.out.println("

Reading SerializeTest object from disk

"); FileInputStream in = new FileInputStream("serialized.txt"); ObjectInputStream si = new ObjectInputStream(in); SerializeTest fromdisk = (SerializeTest)si.readObject(); /* x will be 0 because it won't be read from disk since transient */ System.out.println("After Read := " + fromdisk); } }

Documentation Generation from Source Code Comments Both C# and Java provide a mechanism for extracting specially formatted comments from source code and placing them in an alternate document. These comments are typically API specifications and are very useful way to provide API documentation to the users of a library. The generated documentation is also useful to share the specifications for an API between designers, developers and QA. Javadoc is the tool used to extract API documentation from source code. Javadoc generates HTML documentation from the source code comment, an example of which is the Java™ Platform, Standard Edition API Documentation which was all generated using Javadoc. Javadoc can be used to describe information at the package, class, member and method level. Descriptions of classes and member variables can be provided with the option to add references to other classes, class members and methods. Javadoc allows one to document the following metadata about a method: Description of the method.

Exceptions thrown by the method.

Parameters the method accepts

Return type of the method.

Associated methods and members.

Indication as to whether the API has been deprecated or not.

Version of the API the method was first added. The deprecated information is also used by the compiler which issues a warning if a call to a method marked with the deprecated tag is encountered during compilation.



Javadoc also provides the following information automatically: Inherited API

List of derived classes

List of implementing classes for interfaces

Serialized form of the class

Alphabetical class listing.

Package hierarchy in a tree format.



Since Javadoc generates HTML documentation, it is valid to use HTML in Javadoc comments. There is support for linking the generated documentation with other generated documentation available over the web. Such linking is useful when one wants readers of the documentation to be able to read the API documentation from the related sources. An example of this is the following generated documentation which contains links to the Java 2 API documentation. If no such linking is specified then the generated documentation contains no links to other API documentation. Below is an example of how Javadoc comments are used Java Code /** * Calculates the square of a number. * @param num the number to calculate. * @return the square of the number. * @exception NumberTooBigException this occurs if the square of the number * is too big to be stored in an int. */ public static int square(int num) throws NumberTooBigException{} C# uses XML as the format for the documentation. The generated documentation is an XML file that contains the metadata specified by the user with very little additional information generated automatically. All the C# XML documentation tags have an analogous Javadoc construct while the same cannot be said for the Javadoc tags having C# XML documentation analogs. For instance, the default C# XML documentation does not have analogs to Javadoc's @author , @version , or @deprecated tags although such metadata can be generated by reflecting on the assembly, as Microsoft's documentation build process does. One could also create custom tags that are analogous to the Javadoc tags and more but they would be ignored by standard tools used for handling C# XML documentation including Visual Studio.NET. Also of note is that C#'s XML documentation when generated does not contain metadata about the class such as listings of inherited API, derived classes or implementing interfaces. Here is an example of an XML file generated from C# source code. The primary benefit of an XML format is that the documentation specification can now be used in many different ways. XSLT stylesheets can then be used to convert the generated documentation to ASCII text, HTML, or Postscript files. Also of note is that the generated documentation can be fed to tools that use it for spec verification or other similar tasks. It should be noted that C# currently does not have a tool analogous to Javadoc for converting the XML documentation into HTML. Microsoft is in the process of developing such a tool which is currently codenamed SandCastle. Below is an example of how C# XML documentation is used. C# Code ///<summary>Calculates the square of a number.</summary> ///<param name="num">The number to calculate.</param> ///<return>The square of the number. </return> ///<exception>NumberTooBigException - this occurs if the square of the number ///is too big to be stored in an int. </exception> public static int square(int num){}

Multiple Classes in a Single File Multiple classes can be defined in a single file in both languages with some significant differences. In Java, there can only be one class per source file that has public access and it must have the same name as the source file minus the file extension. C# does not have a restriction on the number of public classes that can exist in a source file and neither is there a requirement for the name of any of the classes in the file to match that of the source file.

Importing Libraries Using libraries in an application is a two-step process. First the needed libraries must be referenced somewhere in the source file which is done via the using keyword in C# and the import keyword in Java. Secondly, there must be a way to tell the compiler where to find the location of the needed library. Specifying the location of libraries that will be used by a Java program is done using the CLASSPATH environment variable or the -classpath compiler option. Assembly locations are specified with the /r compiler switch in C#.

Events Event-driven programming is a programming model where objects can register themselves to be notified of a specific occurrence or state change in another object. Event-driven programming is also referred to as the publish-subscribe model or the observer design pattern and is very popular in graphical user interface (GUI) programming. Java and C# both have mechanisms that support events but there are significant differences. The typical publish-subscribe model has a one to many relationship between an object (publisher) and its event handlers (subscribers). A subscriber is registered by invoking a method on the publisher which then adds the subscriber to an internal collection of interested objects. When the state change that a registered subscriber is interested in occurs, a method is invoked in the publisher that cycles through the collection of subscribers and invokes a callback method on each one. There is no general mechanism for event handling in Java. Instead there are design patterns that are used by the GUI classes which developers can take their cue from. An event is typically a subclass of the java.util.EventObject class, which has methods that enable setting or getting of the object that was the source of the event. A subscriber in the Java model usually implements an interface that ends with the word Listener (e.g. MouseListener, ActionListener, KeyListener, etc) which should contain a callback method that would be called by the publisher on the occurrence of the event. The publisher typically has a method that begins with add and ends with Listener (e.g. addMouseListener, addActionListener, addKeyListener, etc) which is used to register subscribers. The publisher also has remove methods for unregistering the subscribers. The aforementioned components are the primary entities in an event-driven Java program. C# uses delegates to provide an explicit mechanism for creating a publish-subscribe model. An event is typically a subclass of the System.EventArgs class. Like all data classes, the event class should have a constructor that allows complete initialization without calling any other methods so that you can pass new YourEventArgs(inits) to the subscriber delegate. The publisher has a protected method preceded with the word "On" (e.g. OnClick, OnClose, OnInit, etc) which is invoked when a specified event occurs, this method would then invoke the delegate passing it the source and an instance of the EventArgs object. Making the method protected allows derived classes to call it directly without the need to register a delegate. The subscriber is a method that accepts the same argument and returns the same type as the event delegate. The event delegate usually returns void and accepts two parameters; an Object which should be the source of the event and the EventArgs subclass which should represent the event that occured. In C#, the event is used to automatically specify that a field within a subscriber is a delegate that will be used as a callback during an event-driven situation. During compilation the compiler adds overloaded versions of the += and -= operators that are analogous to the add and remove methods that are used in Java to register and unregister a subscriber. The example below shows a class that generates 20 random numbers and fires an event whenever one of the numbers is even. C# Code using System; class EvenNumberEvent: EventArgs{ /* HACK: fields are typically private, but making this internal so it * can be accessed from other classes. In practice should use properties. */ internal int number; public EvenNumberEvent(int number):base(){ this.number = number; } } class Publisher{ public delegate void EvenNumberSeenHandler(object sender, EventArgs e); public event EvenNumberSeenHandler EvenNumHandler; protected void OnEvenNumberSeen(int num){ if(EvenNumHandler!= null) EvenNumHandler(this, new EvenNumberEvent(num)); } //generates 20 random numbers between 1 and 20 then causes and //event to occur if the current number is even. public void RunNumbers(){ Random r = new Random((int) DateTime.Now.Ticks); for(int i=0; i < 20; i++){ int current = (int) r.Next(20); Console.WriteLine("Current number is:" + current); //check if number is even and if so initiate callback call if((current % 2) == 0) OnEvenNumberSeen(current); }//for } }//Publisher public class EventTest{ //callback function that will be called when even number is seen public static void EventHandler(object sender, EventArgs e){ Console.WriteLine("\t\tEven Number Seen:" + ((EvenNumberEvent)e).number); } public static void Main(string[] args){ Publisher pub = new Publisher(); //register the callback/subscriber pub.EvenNumHandler += new Publisher.EvenNumberSeenHandler(EventHandler); pub.RunNumbers(); //unregister the callback/subscriber pub.EvenNumHandler -= new Publisher.EvenNumberSeenHandler(EventHandler); } } Java Code import java.util.*; class EvenNumberEvent extends EventObject{ public int number; public EvenNumberEvent(Object source, int number){ super(source); this.number = number; } } interface EvenNumberSeenListener{ void evenNumberSeen(EvenNumberEvent ene); } class Publisher{ Vector subscribers = new Vector(); private void OnEvenNumberSeen(int num){ for(int i=0, size = subscribers.size(); i < size; i++) ((EvenNumberSeenListener)subscribers.get(i)).evenNumberSeen(new EvenNumberEvent(this, num)); } public void addEvenNumberEventListener(EvenNumberSeenListener ensl){ subscribers.add(ensl); } public void removeEvenNumberEventListener(EvenNumberSeenListener ensl){ subscribers.remove(ensl); } //generates 20 random numbers between 1 and 20 then causes and //event to occur if the current number is even. public void RunNumbers(){ Random r = new Random(System.currentTimeMillis()); for(int i=0; i < 20; i++){ int current = (int) r.nextInt() % 20; System.out.println("Current number is:" + current); //check if number is even and if so initiate callback call if((current % 2) == 0) OnEvenNumberSeen(current); }//for } }//Publisher public class EventTest implements EvenNumberSeenListener{ //callback function that will be called when even number is seen public void evenNumberSeen(EvenNumberEvent e){ System.out.println("\t\tEven Number Seen:" + ((EvenNumberEvent)e).number); } public static void main(String[] args){ EventTest et = new EventTest(); Publisher pub = new Publisher(); //register the callback/subscriber pub.addEvenNumberEventListener(et); pub.RunNumbers(); //unregister the callback/subscriber pub.removeEvenNumberEventListener(et); } }