C# From A Java Developers Perspective
C# From A Java Developers Perspective
http://www.25hoursaday.com/CsharpVsJava.html...
A COMPARISON OF
MICROSOFT'S C# PROGRAMMING LANGUAGE
TO SUN MICROSYSTEMS' JAVA PROGRAMMING
LANGUAGE
By
Dare Obasanjo
Introduction
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 dierences 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.
Quick Index
A. The More Things Change The More They Stay The Same
This section describes concepts and language features that are almost exactly the same in C# and
Java.
1. We Are All Objects
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Keyword Jumble
Of Virtual Machines and Language Runtimes
Heap Based Classes and Garbage Collection
Arrays Can Be Jagged
No Global Methods
Interfaces, Yes. Multiple Inheritance, No.
Strings Are Immutable
Unextendable Classes
Throwing and Catching Exceptions
Member Initialization at Denition and Static Constructors
12. Boxing
1 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
Collections
goto (no longer considered harmful)
Virtual Methods (and nal ones too)
File I/O
Object Serialization
11.
12.
13.
14.
15.
2 of 77
Preprocessor Directives
Aliases
Runtime Code Generation
Pointers and Unsafe Code
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
Pass by Reference
Verbatim Strings
Overow Detection
Explicit Interface Implementation
The More Things Change The More They Stay The Same
1. We Are All Objects
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 dierences (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.
2. Keyword Jumble
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.
3 of 77
C#
Java
C#
keyword keyword keyword
Java
keyword
C#
keyword
C#
Java
keyword keyword
Java
abstract
abstract
extern
native
operator
N/A
throw
throw
as
N/A
false
false
out
N/A
true
true
keyword
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
base
super
nally
nally
override
N/A
try
try
bool
boolean
xed
N/A
params
...
typeof
N/A
break
break
oat
oat
partial
N/A
uint
N/A
byte
N/A
for
for
private
private
ulong
N/A
case
case
foreach
for
protected
N/A
unchecked N/A
catch
catch
get
N/A
public
public
unsafe
N/A
char
char
goto
goto1
readonly
N/A
ushort
N/A
checked
N/A
if
if
ref
N/A
using
import
class
class
implicit
N/A
return
return
value
N/A
const
const1
in
N/A
sbyte
byte
virtual
N/A
int
sealed
nal
void
void
decimal
N/A
interface
interface
set
N/A
volatile
volatile
default
default
internal
protected
short
short
where
extends
delegate N/A
is
instanceof
sizeof
N/A
while
while
do
do
lock
yield
N/A
double
double
long
long
else
else
enum
static
static
extends
namespace package
string
N/A
implements
N/A
new
new
struct
N/A
N/A
strictfp
event
N/A
null
null
switch
switch
N/A
throws
explicit
N/A
object
N/A
this
this
N/A
transient2
NOTE: Although
NOTE: The
goto
and
[NonSerialized]
const
are Java language keywords they are unused in the Java language.
transient
keyword in Java.
4 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
6. No Global Methods
Just like Java and unlike C++, methods in C# have to be part of a class either as member or static
methods.
7. Interfaces, Yes. Multiple Inheritance, No
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.
8. Strings Are Immutable
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# Code
String csString = "Apple Jack";
csString.ToLower(); /* Does not modify string, instead returns lower case copy of string */
Java Code
String jString = "Grapes";
jString.toLowerCase(); /* Does not modify string, instead returns lower case copy of string */
string
or String.
9. Unextendable Classes
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# Code
sealed class Student {
string fname;
string lname;
int uid;
void attendClass() {}
5 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
Java Code
final class Student {
String fname;
String lname;
int uid;
void attendClass() {}
}
}
public class ExceptionTest {
6 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
}//Main(string[])
} // ExceptionTest
Java Code
class MyException extends Exception{
public MyException(String message){ super(message); }
public MyException(String message, Exception innerException){ super(message, innerException); }
}
public class ExceptionTest {
7 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
StaticInitTest(){
Console.WriteLine("In instance constructor");
}
static StaticInitTest(){
Console.WriteLine("In static constructor");
}
StaticInitTest(){
System.out.println("In instance constructor");
}
static{
System.out.println("In static constructor");
}
8 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
12. Boxing
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.
C# Code
using System;
using System.Collections;
//stack allocated structs also need to be boxed to be treated as objects
struct Point{
//member fields
private int x;
private int y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public override string ToString(){
return String.Format("({0}, {1})", x, y);
}
}//Point
class Test{
9 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
public static void Main(string[] args){
Point p = new Point(10, 15);
ArrayList list = new ArrayList();
int z = 100;
PrintString(p); //p boxed to object when passed to PrintString
PrintString(z); //z boxed to object when passed to PrintString
// integers and float boxed when stored in collection
// therefore no need for Java-like wrapper classes
list.Add(1);
list.Add(13.12);
list.Add(z);
for(int i =0; i < list.Count; i++)
PrintString(list[i]);
}
}
Java Code
import java.util.*;
class Test{
public static void PrintString(Object o){
System.out.println(o);
}
public static void PrintInt(int i){
System.out.println(i);
}
public static void main(String[] args){
Vector list = new Vector();
int z = 100;
Integer x = new Integer(300);
PrintString(z); //z boxed to object when passed to PrintString
PrintInt(x); //x unboxed to int when passed to PrintInt
// integers and float boxed when stored in collection
// therefore no need for Java wrapper classes
list.add(1);
list.add(13.12);
list.add(z);
for(int i =0; i < list.size(); i++)
PrintString(list.elementAt(i));
}
}
10 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
by convention) while the main method in Java begins with a lowercase "m" (as do all Java method
names, by convention). The declaration for the main method is otherwise the same in both cases
except for the fact that parameter to the Main() method in C# can have a void parameter.
C# Code
using System;
class A{
public static void Main(String[] args){
Console.WriteLine("Hello World");
}
}
Java Code
class B{
public static void main(String[] args){
System.out.println("Hello World");
}
}
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 specic class one wants run via the command
line to run its main method. In C# one can get the same eect 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.
Java Example
C:\CodeSample> javac A.java B.java
C:\CodeSample> java A
Hello World from class A
C:\CodeSample> java B
Hello World from class B
C# Example
C:\CodeSample> csc /main:A /out:example.exe A.cs B.cs
C:\CodeSample> example.exe
Hello World from class A
C:\CodeSample> csc /main:B /out:example.exe A.cs B.cs
C:\CodeSample> example.exe
Hello World from class B
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.
2. Inheritance Syntax
C# uses C++ syntax for inheritance, both for class inheritance and interface implementation as
opposed to the extends and implements keywords.
C# Code
11 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
using System;
class B:A, IComparable{
int CompareTo(){}
public static void Main(String[] args){
Console.WriteLine("Hello World");
}
}
Java Code
class B extends A implements Comparable{
int compareTo(){}
public static void main(String[] args){
System.out.println("Hello World");
}
}
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.
3. Run Time Type Identication (is operator)
The C# is operator is completely analogous to Java's
are equivalent.
instanceof
C# Code
if(x is MyClass)
MyClass mc = (MyClass) x;
Java Code
if(x instanceof MyClass)
MyClass mc = (MyClass) x;
4. Namespaces
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 les in an application
whereas in C# namespaces do not dictate the physical layout of source les in directories only their
logical structure. Examples below:
C# Code
namespace com.carnage4life{
public class MyClass {
int x;
12 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
void doStuff(){}
}
}
Java Code
package com.carnage4life;
public class MyClass {
int x;
void doStuff(){}
}
C#
namespace
C# Code
using System;
namespace Company{
public class MyClass { /* Company.MyClass */
int x;
void doStuff(){}
}
namespace Carnage4life{
public class MyOtherClass {
/* Company.Carnage4life.MyOtherClass */
int y;
void doOtherStuff(){}
public static void Main(string[] args){
Console.WriteLine("Hey, I can nest namespaces");
}
}// class MyOtherClass
}// namespace Carnage4life
}// namespace Company
13 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
14 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
synchronized(this){
if(num < this.amount)
this.amount -= num;
}
}
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 rst thread
when it nishes 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
C# Code
using System;
using System.Runtime.CompilerServices;
public class BankAccount{
[MethodImpl(MethodImplOptions.Synchronized)]
public void WithdrawAmount(int num){
if(num < this.amount)
this.amount - num;
}
}//BankAccount
Java Code
public class BankAccount{
public synchronized void withdrawAmount(int num){
if(num < this.amount)
this.amount - num;
}
}//BankAccount
7. Access Modiers
Below is a table mapping C# access modiers 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 modier means that the member can be accessed from other classes in
the same assembly as the class. The internal protected modier means that a member can be accessed
from classes that are in the same assembly or from derived classes.
C# access modier Java access modier
15 of 77
private
private
public
public
internal
protected
protected
N/A
04/05/2016 10:56 AM
internal protected
http://www.25hoursaday.com/CsharpVsJava.html...
N/A
NOTE: The default accessibility of a C# eld or method when no access modier is specied is private
while in Java it is protected (except that derived classes from outside the package cannot inherit the
eld).
8. Reection
The ability to discover the methods and elds in a class as well as invoke methods in a class at
runtime, typically called reection, is a feature of both Java and C#. The primary dierence between
reection in Java versus reection in C# is that reection in C# is done at the assembly level while
reection in Java is done at the class level. Since assemblies are typically stored in DLLs, one needs
the DLL containing the targeted class to be available in C# while in Java one needs to be able to load
the class le for the targeted class. The examples below which enumerate the methods in a specied
class should show the dierence between reection in C# and Java.
C# Code
using
using
using
using
System;
System.Xml;
System.Reflection;
System.IO;
class ReflectionSample {
Assembly assembly=null;
Type type=null;
XmlDocument doc=null;
try{
// Load the requested assembly and get the requested type
assembly = Assembly.LoadFrom("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.2914\\System.XML.dll");
type = assembly.GetType("System.Xml.XmlDocument", true);
//Unfortunately one cannot dynamically instantiate types via the Type object in C#.
doc = Activator.CreateInstance("System.Xml","System.Xml.XmlDocument").Unwrap() as XmlDocument;
if(doc != null)
Console.WriteLine(doc.GetType() + " was created at runtime");
else
Console.WriteLine("Could not dynamically create object at runtime");
}catch(FileNotFoundException){
Console.WriteLine("Could not load Assembly: system.xml.dll");
return;
}catch(TypeLoadException){
Console.WriteLine("Could not load Type: System.Xml.XmlDocument from assembly: system.xml.dll");
return;
}catch(MissingMethodException){
Console.WriteLine("Cannot find default constructor of " + type);
}catch(MemberAccessException){
Console.WriteLine("Could not create new XmlDocument instance");
}
// Get the methods from the type
MethodInfo[] methods = type.GetMethods();
//print the method signatures and parameters
for(int i=0; i < methods.Length; i++){
Console.WriteLine ("{0}", methods[i]);
ParameterInfo[] parameters = methods[i].GetParameters();
16 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().getClass();
(Document) c.newInstance();
One might notice from the above code samples that there is slightly more granularity in the C#
Reection API than the Java Reection 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.
Sometimes there is a need to obtain the metadata of a specic 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
C# Code
Type t = typeof(ArrayList);
17 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
Java Code
Class c = java.util.Arraylist.class; /* Must append ".class" to fullname of class */
9. Declaring Constants
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 dened in the constructor.
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.
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.
C# Code
using System;
public class ConstantTest{
/* Compile time constants */
const int i1 = 10;
//implicitly a static variable
// code below won't compile because of 'static' keyword
// public static const int i2 = 20;
/* run time constants */
public static readonly uint l1 =
(uint) DateTime.Now.Ticks;
ConstantTest() {
// unitialized readonly variable must be initialized in constructor
f = 17.21f;
}
}
Java Code
import java.util.*;
public class ConstantTest{
/* Compile time constants */
final int i1 = 10;
//instance variable
static final int i2 = 20; //class variable
/* run time constants */
public static final long l1 = new Date().getTime();
/* object reference as constant */
final Vector v = new Vector();
18 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
/* uninitialized final */
final float f;
ConstantTest() {
// unitialized final variable must be initialized in constructor
f = 17.21f;
}
}
final
The primary use of nal parameters is to allow arguments to a method to be accessible from within
inner classes declared in the method body.
10. Primitive Types
For every Java primitive type there is a corresponding C# type which has the same name (except for
byte). The byte type in Java is signed and is thus analagous to the sbyte type in C# and not the byte
type.C# also has unsigned versions of some primitives such as ulong, uint, ushort and byte . The only
signicantly dierent primitive in C# is the decimal type, a type which stores decimal numbers without
rounding errors (at the cost of more space and less speed).
Below are dierent ways to declare real valued numbers in C#.
C# Code
decimal dec = 100.44m; //m is the suffix used to specify decimal numbers
double dbl = 1.44e2d; //e is used to specify exponential notation while d is the suffix used for doubles
19 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
C# Code
using System;
class MyException: Exception
{
private int Id;
public MyException(string message): this(message, null, 100){ }
public MyException(string message, Exception innerException):
this(message, innerException, 100){ }
public MyException(string message, Exception innerException, int id):
base(message, innerException){
this.Id = id;
}
}
Java Code
20 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
14. Generics
Both C# and Java provide a mechanism for creating strongly typed data structures without knowing
the specic 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
specic types at runtime. This technique had several drawbacks including lack of type safety, poor
performance and code bloat.
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.
C# Code
using System;
using System.Collections;
using System.Collections.Generic;
class Test{
public static Stack GetStackB4Generics(){
Stack s = new Stack();
s.Push(2);
s.Push(4);
s.Push(5);
return s;
}
public static Stack<int> GetStackAfterGenerics(){
Stack<int> s = new Stack<int>();
s.Push(12);
s.Push(14);
s.Push(50);
return s;
}
public static void Main(String[] args){
Stack s1 = GetStackB4Generics();
int sum1 = 0;
21 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
while(s1.Count != 0){
sum1 += (int) s1.Pop(); //cast
}
Console.WriteLine("Sum of stack 1 is " + sum1);
Stack<int> s2 = GetStackAfterGenerics();
int sum2 = 0;
while(s2.Count != 0){
sum2 += s2.Pop(); //no cast
}
Console.WriteLine("Sum of stack 2 is " + sum2);
}
}
Java Code
import java.util.*;
class Test{
public static Stack GetStackB4Generics(){
Stack s = new Stack();
s.push(2);
s.push(4);
s.push(5);
return s;
}
public static Stack<Integer> GetStackAfterGenerics(){
Stack<Integer> s = new Stack<Integer>();
s.push(12);
s.push(14);
s.push(50);
return s;
}
public static void main(String[] args){
Stack s1 = GetStackB4Generics();
int sum1 = 0;
while(!s1.empty()){
sum1 += (Integer) s1.pop(); //cast
}
System.out.println("Sum of stack 1 is " + sum1);
Stack<Integer> s2 = GetStackAfterGenerics();
int sum2 = 0;
while(!s2.empty()){
sum2 += s2.pop(); //no cast
}
System.out.println("Sum of stack 2 is " + sum2);
}
}
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.
Specically 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 reection or run time type
22 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
identication. 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.
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 specic 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
specic type is returned. If not, the JIT compiler instantiates a new type by replacing the generic type
parameters in the IL with the specic 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.
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 specic type (e.g. a method to print all the objects in a data
structure) while still taking advantage of the benets 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.
C# Code
using System;
using System.Collections;
using System.Collections.Generic;
class Test{
//Prints the contents of any generic Stack by
//using generic type inference
public static void PrintStackContents<T>(Stack<T> s){
while(s.Count != 0){
Console.WriteLine(s.Pop());
}
}
public static void Main(String[] args){
Stack<int> s2 = new Stack<int>();
s2.Push(4);
s2.Push(5);
s2.Push(6);
PrintStackContents(s2);
Stack<string> s1 = new Stack<string>();
s1.Push("One");
s1.Push("Two");
s1.Push("Three");
PrintStackContents(s1);
}
}
Java Code
import java.util.*;
class Test{
//Prints the contents of any generic Stack by
//specifying wildcard type
public static void PrintStackContents(Stack<?> s){
while(!s.empty()){
System.out.println(s.pop());
}
}
public static void main(String[] args){
Stack <Integer> s2 = new Stack <Integer>();
23 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
s2.push(4);
s2.push(5);
s2.push(6);
PrintStackContents(s2);
Stack<String> s1 = new Stack<String>();
s1.push("One");
s1.push("Two");
s1.push("Three");
PrintStackContents(s1);
}
}
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
1. A derivation constraint indicates to the compiler that the generic type parameter derives from a
base type such an interface or a particular base class
2. A default constructor constraint indicates to the compiler that the generic type parameter
exposes a public default constructor
3. A reference/value type constraint constrains the generic type parameter to be a reference or a
value type.
In Java, only the derivation constraint is supported. The following code sample shows how constraints
are used in practice.
C# Code
using System;
using System.Collections;
using System.Collections.Generic;
public class Mammal {
public Mammal(){;}
public virtual void Speak(){;}
}
public class Cat : Mammal{
public Cat(){;}
public override void Speak(){
Console.WriteLine("Meow");
}
}
public class Dog : Mammal{
public Dog(){;}
public override void Speak(){
Console.WriteLine("Woof");
}
}
24 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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 (lling the structure with zeros). This operator is very useful when combined with
generics. The following code sample excercises the functionality of this operator.
C# Code
using System;
public class Test{
public static T GetDefaultForType(){
return default(T); //return default value of type T
}
public static void Main(String[] args){
Console.WriteLine(GetDefaultForType<int>());
Console.WriteLine(GetDefaultForType<string>());
Console.WriteLine(GetDefaultForType<float>());
25 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
}
in
are used when creating the for-each loop while in Java the keyword
C# Code
string[] greek_alphabet = {"alpha", "beta", "gamma", "delta", "epsilon"};
foreach(string str in greek_alphabet)
Console.WriteLine(str + " is a letter of the greek alphabet");
Java Code
String[] greek_alphabet = {"alpha", "beta", "gamma", "delta", "epsilon"};
for(String str : greek_alphabet)
System.out.println(str + " is a letter of the greek alphabet");
II.
III.
[MethodImpl(MethodImplOptions.Synchronized)]:
is used to mark a class as serializable and is similar to a Java class implementing the
Serializable interface.
[FlagsAttribute]:
26 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
//.. do something
}
IV.
[WebMethod]:
is used in combination with ASP.NET to specify that a method should be available over
the web as a web service automatically. Doing the same in Java involves conguring JAXP, UDDI,
and J2EE as well as have to create an Enterprise Java Bean which involves at least two interfaces
and one implementation class plus setting up the deployment descriptor. For more information on
webservices in C#, examine the Your First C# Web Service page on CodeProject.
It is possible to access the attributes of a module, class, method or eld via reection. 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 reection to access that information.
C# Code
using System;
using System.Reflection;
[AttributeUsage(AttributeTargets.Class)]
public class AuthorInfoAttribute: System.Attribute{
string author;
string email;
string version;
get{
return version;
}
set{
version = value;
}
}
get{
return email;
}
}
public string Author{
get{
return author;
}
}
}
27 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
class AttributeTest{
public static void Main(string[] args){
/* Get Type object of HelloWorld class */
Type t = typeof(HelloWorld);
Console.WriteLine("Author Information for " + t);
Console.WriteLine("=================================");
foreach(AuthorInfoAttribute att in t.GetCustomAttributes(typeof(AuthorInfoAttribute), false)){
Console.WriteLine("Author: " + att.Author);
Console.WriteLine("Email: " + att.Email);
Console.WriteLine("Version: " + att.Version);
}//foreach
}//Main
}
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.
I.
II.
III.
@Override:
is used to specify that a method is intended to override a method in a base class. If the
annotated method does not override a method in the base class then an error is issued during
compilation.
@Deprecated:
is used to indicate that a particular method has been deprecated. If the annotated
method is used then a warning is issued during compilation.
@SuppressWarnings:
is used to prevent particular warnings from being issued by the compiler. This
annotation optionally takes the name of the specic warning to suppress as an argument.
As in C# it is possible to access the annotations on a module, class, method or eld via reection.
However a key dierence 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 dene it. What follows is an example of using an
attribute to provide information about the author of a class then using reection to access that
information.
Java Code
import java.lang.annotation.*;
import java.lang.reflect.*;
@Documented //we want the annotation to show up in the Javadocs
@Retention(RetentionPolicy.RUNTIME) //we want annotation metadata to be exposed at runtime
@interface AuthorInfo{
String author();
String email();
String version() default "1.0";
}
@AuthorInfo(author="Dare Obasanjo", email="kpako@yahoo.com")
class HelloWorld{
}
28 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
17. Enumerations
Enums are used to create and group together a list of user dened named constants. Although on the
surface the enumerated types in C# and Java seem quite similar there are some signicant dierences
in the implementation of enumerated types in both languages. In Java, enumerated types are a full
edged class which means they are typesafe and can be extended by adding methods, elds 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.
The following code sample highlights the dierences between enums in both languages.
C# Code
using System;
public enum DaysOfWeek{
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
public class Test{
public static bool isWeekDay(DaysOfWeek day){
return !isWeekEnd(day);
}
public static bool isWeekEnd(DaysOfWeek day){
return (day == DaysOfWeek.SUNDAY || day == DaysOfWeek.SATURDAY);
}
public static void Main(String[] args){
DaysOfWeek sun = DaysOfWeek.SUNDAY;
Console.WriteLine("Is " + sun + " a weekend? " + isWeekEnd(sun));
Console.WriteLine("Is " + sun + " a week day? " + isWeekDay(sun));
/* Example of how C# enums are not type safe */
sun = (DaysOfWeek) 1999;
Console.WriteLine(sun);
}
}
Java Code
enum DaysOfWeek{
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
29 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
THURSDAY,
FRIDAY,
SATURDAY;
public boolean isWeekDay(){
return !isWeekEnd();
}
public boolean isWeekEnd(){
return (this == SUNDAY || this == SATURDAY);
}
}
public class Test{
public static void main(String[] args) throws Exception{
DaysOfWeek sun = DaysOfWeek.SUNDAY;
System.out.println("Is " + sun + " a weekend? " + sun.isWeekEnd());
System.out.println("Is " + sun + " a week day? " + sun.isWeekDay());
}
}
NOTE: In Java a nested class can be declared in any block of code including methods, this is not the
30 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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.
2. Threads and Volatile Members
A thread is a sequential ow 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 specically 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 specic order and
must be processed in the same order upon return. Due to the non-deterministic nature of threads, on
some runs the threads nish 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");
}
31 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
//Console.WriteLine(idNumber + ":B");
owner.workCompleted(this);
}/* performTask() */
} // WorkerThread
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
32 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
/* 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.*;
} // WorkerThread
33 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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
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 elds is prohibited. There are major dierences 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();
34 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
}
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.
3. 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 exibility 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 benecial
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#.
35 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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();
}
4. switch Statment
There are two major dierences 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-nd
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" */
36 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
case "D":
Console.WriteLine("D seen");
case "E":
Console.WriteLine("E seen");
break;
}
5. Assemblies
C# assemblies share a lot in common with Java JAR les. 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 les 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 les perform a similar task in Java
with most dierences being in the implementation. Assemblies are usually stored as EXEs or DLLs
while JAR les are stored in the ZIP le format.
6. 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 benet 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 retrotted 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; nd the largest element based on some Comparator, nd the smallest
element, nd sublists within a list, reverse the contents of a list, shue 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#.
37 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
goto
statement;
C# Code
using System;
using System.Net.Sockets;
class GotoSample{
38 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
method that has the same signature as the nal base class method.
Below are examples that show the dierences 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);
}
}
39 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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
DoStu(string) method in the Parent class as virtual and marking the DoStu(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);
}
}
The above example can be made to produce the original results by altering the signature of the
DoStu(string) method in the Child class to
public new void DoStuff(string str)
which states that although the DoStu method is virtual in the base class, the child class would like to
treat it as a non-virtual method.
40 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
9. File I/O
Both languages support performing I/O via Stream classes. The examples below copy the contents of a
le named "input.txt" to another called "output.txt".
C# Code
using System;
using System.IO;
= new StreamReader(inputFile);
= 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
41 of 77
[Serializable]
attribute. The
[NonSerialized]
attribute is
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
used to annote members of a C# class that should not be serialized by the runtime. Such elds 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 eicient. One can also dene custom ways an object is serialized if
the standard ways are insuicient 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 species the readExternal() and writeExternal() for use in customizing how an object is read and
written to a stream.
C# Code
using
using
using
using
using
using
System;
System.IO;
System.Reflection;
System.Runtime.Serialization;
System.Runtime.Serialization.Formatters.Binary;
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("\n Writing SerializeTest object to disk");
Stream output = File.Create("serialized.bin");
BinaryFormatter bwrite = new BinaryFormatter();
bwrite.Serialize(output, st);
output.Close();
Console.WriteLine("\n Reading SerializeTest object from disk\n");
Stream input = File.OpenRead("serialized.bin");
BinaryFormatter bread = new BinaryFormatter();
SerializeTest fromdisk = (SerializeTest)bread.Deserialize(input);
42 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
input.Close();
43 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
}
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 specied
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.
44 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
C# uses XML as the format for the documentation. The generated documentation is an XML le that
contains the metadata specied 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 reecting 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 le generated from C# source code.
The primary benet of an XML format is that the documentation specication can now be used in many
dierent ways. XSLT stylesheets can then be used to convert the generated documentation to ASCII
text, HTML, or Postscript les. Also of note is that the generated documentation can be fed to tools
that use it for spec verication 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){}
45 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
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 specied 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 eld 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 res 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));
}
46 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}//Publisher
47 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}//Publisher
48 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
Cross language interoperability is the ability to access constructs written in one programming
language from another. There are a number of ways cross language interoperability works in Java.
First of all, there is the Java Native Interface (JNI) which is a mechanism that allows Java programs
call native methods written in C, C++ or assembly language. The C, C++ or assembly methods
methods must be specically written to be called from Java. Native methods can use JNI to access Java
features such as calling Java language methods, instantiating and modifying Java classes, throwing and
catching exceptions, performing runtime type checking, and loading Java classes dynamically. To
create a JNI program one performs the following steps:
1. Create a Java program that contains the declaration of the native method(s) marked with the
native keyword.
2. Write a main method that loads the library created in step 6 and uses the native method(s).
3. Compile the class containing the declaration of the native method(s) and the main with the javac
compiler.
4. Use the javah compiler with the -jni compiler option to generate a header le for the native
method(s).
5. Write the native method in your language of choice (currently C, C++ or assembly).
6. Compile the header le and native source le into a shared library (i.e. a .dll on Windows or a .so
le on UNIX).
Java also has the ability to interact with distributed objects that use the common object request broker
architecture (CORBA) via Java IDL. CORBA is a technology that allows developers to make procedure
calls on objects in a location and language agnostic manner. A CORBA application usually consists of
an object request broker (ORB), a client and a server. An ORB is responsible for matching a requesting
client to the server that will perform the request, using an object reference to locate the target object.
When the ORB examines the object reference and checks if the target object is remote or not. If the
target of the call is local then the ORB performs an inter-process communication (IPC) call. On calls to
remote objects the ORB marshals the arguments and routes the invocation out over the network to the
remote object's ORB. The remote ORB then invokes the method locally and sends the results back to
the client via the network. CORBA has a language-agnostic interface denition language (IDL) which
for which languages that support CORBA have various mappings. Java IDL supports the mappings
from Java objects to CORBA IDL objects. Various ORBs support CORBA language bindings for a
number of languages including C, C++, Java, Python, Lisp, Perl, and Scheme.
The most seamless way to do cross language interop in Java is when the language is compiled directly
to Java byte code. This means that objects in that language are available to Java programs and Java
objects are available to programs written in the target language. A good example of this is the Jython
scripting language which is a version of the Python programming language that is integrated with the
Java platform. Below is an example of an interactive session with Jython shows how a user could create
an instance of the Java random number class (found in java.util.Random) and then interact with that
instance which was taken from the Jython Documentation
C:\jython>jython
Jython 2.0 on java1.2.1
Type "copyright", "credits" or "license" for more information.
>>> from java.util import Random
>>> r = Random()
>>> r.nextInt()
-790940041
>>> for i in range(5):
...
print r.nextDouble()
...
0.23347681506123852
0.8526595592189546
0.3647833839988137
0.3384865260567278
0.5514469740469587
49 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
>>>
There are a number of projects in various degrees of completion that are aimed at providing a similar
degree of cross language interoperability within the connes of the Java Virtual Machine. A list of
languages retargetted for the Java Virtual Machine is available on the webpage of Dr. Robert Tolksdorf.
Currently, Sun Microsystems (creators of the Java language and platform) seems to be uninterested in
this level of cross language interoperability and has decided to leave this to independent developers
and researchers.
With seamless cross langauge interoperability, objects can inherit implementation from other types,
instantiate and invoke methods dened on other types, and otherwise interact with objects regardless
of the language the types are originally implemented in. Also tools such as class browsers, debuggers,
and prolers only need to understand one format (be it Java byte codes or .NET instruction language)
but can support a multitude of languages as long as they target the appropriate runtime. Also error
handling across languages via exceptions is possible.
C# and the .NET runtime were created with seamless cross-language interoperability as a design goal.
A language targeting the .NET common language runtime (CLR) is able to interact with other
languages that conform to the common type system and when compiled include certain metadata. The
common type system denes how types are declared, used, and managed in the .NET runtime thus
creating a framework that allows for type safety and ensures that objects written in various languages
can share type information. Metadata is binary information describing the assemblies, types and
attributes dened in the application that are stored either in a CLR portable executable (PE) or in
memory if the assembly has been loaded. Langauges that are currently being developed to target the
.NET runtime include APL, C#, C++, COBOL, Component Pascal, Eiel, Haskel#/Mondrian, Java,
Mercury, Oberon, Perl, Python, Scheme, Smalltalk, Standard ML, and Visual Basic.
Since it is very possible that certain features in one language have no analog in another, the .NET
Framework provides the Common Language Specication (CLS), which describes a fundamental set of
language features and denes rules for how those features are used. The CLS rules are a subset of the
common type system that is aimed at ensuring cross-language interoperability by dening a set of
features that are most common in programming languages. The C# compiler is a CLS compliant
compiler meaning that it can be used to generate code that complies with the CLS. The C# compiler
can check for CLS compliance and issues an error when a program code uses functionality that is not
supported by the CLS. To get the C# compiler to check for the CLS compliance of a piece of code,
mark it with the [CLSCompliantAttribute(true)] attribute.
Another aspect of cross language interoperability supported by C# is interaction with COM based
objects. There are mechanisms that allow developers to use COM objects from C# code and vice versa.
C# objects can utilize COM objects if a wrapper class is rst created that denes the functions
available in the COM object as well as some additional information. The wrapper class can then be
used as if it were a regular C# object while the .NET runtime handles the complexities of marshalling
arguments and the like. Creating the wrapper class can be done automatically using the tlbimp utility. If
the utility is unable to create a type library then one must be written by hand with foreknowledge of
the coclasses and interfaces being dened as well as the type library-to-assembly conversion rules.
For a COM object to utilize a C# object, a typelib must be created that describes the C# object to
COM aware applications. The tlbexp can be used to create a typelib that describes the C# object's
interface in a COM-like manner. Also the regasm utility can be used to register an assembly so it is
available to COM. When COM objects interact with the C# object, the runtime handles whatever
marshalling of data that needs to occur between COM and .NET automatically.
C# programs can also call almost any function in any DLL using a combination of the extern keyword
and the DllImport attribute on the method declaration. A major advantage of this is that the method
being called does not have to be specically written to be called from C#, nor is any "wrapper"
necessary-so calling existing code in DLLs is relatively simple.
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
~MyClass(){
Dispose(false);
}
public void Dispose(){
if(!disposed){
Dispose(true);
}
}
51 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
disposed = true;
}
}
}
*/
}//Main
}
The above idiom is practically the same as having C++ style destructors without the worry of having
to deal with memory allocation woes, making it the best of both worlds. The non-deterministic nature
of nalization has long been bemoaned by Java developers, it is a welcome change to see that this will
not be the case when using C#.
NOTE: Calling the Dispose() method does not request that the object is garbage collected , although it
does speed up collection by eliminating the need for nalization. .
2. Delegates
Delegates are a mechanism for providing callback functions. Delegates are akin to function pointers in
C or functors in C++ and are useful in the same kinds of situation. One use of delegates is passing
operations to a generic algorithm based on the types being used in the algorithm. The C function
qsort() is an example of this as are a variety of the C++ functions in <algorithm> like replace_if() and
transform(). Another use of delegates is as a means to register handlers for a particular event (i.e. the
publish-subscribe model). To get the same functionality as C# delegates in Java, once can create
interfaces that specify the signature of the callback method such as is done with the Comparable
interface although this has the drawback of forcing the method to be an instance method when it most
likely should be static.
To use delegates, one rst declares a delegate that has the return type and accepts the same number
of parameters as the methods one will want to invoke as callback functions. Secondly one needs to
dene a method that accepts an instance of the delegate as a parameter. Once this is done, a method
that has the same signature as the delegate (i.e. accepts same parameters and returns the same type)
or has covariant return types and contravariant parameter types (i.e return type is derived from the
return type of the delegate and the parameter types are ancestors of the corresponding parameters)
can be created and used to initialize an instance of the delegate which can then be passed to the
method that accepts that delegate as a parameter. Note that the same delegate can refer to static and
52 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
instance methods, even at the same time, since delegates are multicast. The example below shows the
process of creating and using instance delegates.
C# Code
using System;
/* Mammal class hierarchy used to show return type covariance */
public class Mammal {
public Mammal(){;}
public virtual void Speak(){;}
}
public class Cat : Mammal{
public Cat(){;}
public override void Speak(){
Console.WriteLine("Meow");
}
}
public class Dog : Mammal{
public Dog(){;}
public override void Speak(){
Console.WriteLine("Woof");
}
}
= new Dog();
A delegate can be passed as a parameter to a method in the same way that a function pointer is passed
in languages like C and C++. The following code sample shows how this is done.
C# Code
using System;
//delegate base
53 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
54 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
using System;
struct Point {
public int x;
public int y;
public Point( int x, int y){
this.x = x;
this.y = y;
}
public override string ToString(){
return String.Format("({0}, {1})", x, y);
}
NOTE: The
as
5. Properties
Properties are a way to abstract away from directly accessing the members of a class, similar to how
accessors (getters) and modiers (setters) are used in the Java world. A property is accessed by users
of a class as if it was a eld or member variable but in actuality is a method call. Accessing a member
via a property allows for side eects when setting values or calculations when generating values while
being transparent to the user of the class. Properties thus provide an explicit way to decouple the
implementation of the member access from how it is actually used.
It is possible to create, read-only, write-only or read-write properties depending on if the getter and
setter are implemented or not. In addition, it is possible to create a property whose getter and setter
have dierent visibility (e.g. a public getter but a private setter). The example below shows dierent
kinds of properties.
C# Code
using System;
55 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
The use of properties as an abstraction away from whether a member access is a method call or not
may fall apart if the property throws an exception. When this occurs users of the object must then
treat operations that look like member accesses as if they were method calls which can lead to
unintuitive looking code. The example below shows code that sets the values for the elds of a Clock
class that where the setters throw an exception if the value is invalid.
C# Code
try{
myClock.Hours
= 28;
myClock.Minutes = 15;
myClock.Seconds = 39;
}catch(InvalidTimeValueException itve){
56 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
To avoid situations like the one in the above example it is best that one avoids throwing exceptions in
properties and handle the exceptions that are thrown by methods used in the property. If throwing an
exception is avoidable in some situations then the documentation for the property must adequately
describe the exceptions that can be thrown and the circumstances that lead to them being thrown.
6. Multidimensional Arrays
C# makes the distinction between multidimensional and jagged arrays. A multidimensional array is
akin to a multidimensional array in C or C++ that is a contiguous block containing members of the
same type. A jagged array is akin to an array in Java which is an array of arrays, meaning that it
contains references to other arrays which may contain members of the same type or other arrays
depending on how many levels the array has. The code snippets below highlight the dierences
between multidimensional and jagged arrays. The lack of true multidimensional arrays in Java has
made it problematic to use Java in certain aspects of technical computing which has lead to various
eorts to improve this position including research eorts by IBM which involved writing their own
Array class to get around the shortcomings in Java arrays.
The following code snippet emphasizes the dierences between using multidimensional arrays and
jagged arrays in C#.
C# Code
using System;
57 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
7. Indexers
An indexer is a special syntax for overloading the [] operator for a class. An indexer is useful when a
class is a container for another kind of object. Indexers are exible in that they support any type, such
as integers or strings, as indexes. It is also possible to create indexers that allow multidimensional
array syntax where one can mix and match dierent types as indexes. Finally, indexers can be
overloaded.
C# Code
using System;
using System.Collections;
public class IndexerTest: IEnumerable, IEnumerator {
private Hashtable list;
public IndexerTest (){
index = -1;
list = new Hashtable();
}
//indexer that indexes by number
public object this[int column]{
get{
return list[column];
}
set{
list[column] = value;
}
}
get{
return this[ConvertToInt(name)];
}
set{
this[ConvertToInt(name)] = value;
}
}
58 of 77
"zero": return 0;
"one": return 1;
"two": return 2;
"three": return 3;
"four": return 4;
"five": return 5;
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
default:
return 0;
}
return 0;
}
/**
* Needed to implement IEnumerable interface.
*/
public IEnumerator GetEnumerator(){ return (IEnumerator) this; }
/**
* Needed for IEnumerator.
*/
private int index;
/**
* Needed for IEnumerator.
*/
public bool MoveNext(){
index++;
if(index >= list.Count)
return false;
else
return true;
}
/**
* Needed for IEnumerator.
*/
public void Reset(){
index = -1;
}
/**
* Needed for IEnumerator.
*/
public object Current{
get{
return list[index];
}
}
59 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
} // IndexerTest
8. Preprocessor Directives
C# includes a preprocessor that has a limited subset of the functionality of the C/C++ preprocessor.
The C# preprocessor lacks the ability to #include les or perform textual substitutions using #define. The
primary functionality that remains is the ability to #define and #undef identiers and also the ability to
select which sections of code to compile based on the validity of certain expressions via #if, #elif, and
#else. The #error and #warning directives cause the errors or warnings messages following these
directives to be printed on compilation. The #pragma directive is used to supress compiler warning
messages. Finally, there is the #line directive that can be used to specify the source le and line
number reported when the compiler detects errors.
C# Code
#define DEBUG /* #define must be first token in file */
using System;
#pragma warning disable 169 /* Disable 'field never used' warning */
class PreprocessorTest{
int unused_field;
public static void Main(string[] args){
#if DEBUG
Console.WriteLine("DEBUG Mode := On");
#else
Console.WriteLine("DEBUG Mode := Off");
#endif
}
}
9. Aliases
The using keyword can be used to alias the fully qualied name for a type similar to the way typedef is
used in C and C++. This is useful in creating readable code where the fully qualied name of a class is
needed to resolve namespace conicts.
C# Code
using Terminal = System.Console;
class Test{
public static void Main(string[] args){
Terminal.WriteLine("Terminal.WriteLine is equivalent to System.Console.Writeline");
}
}
60 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
program.
It is expected that the primary users of the Reflection.Emit namespace will be authors of compilers and
script engines. For instance, the regular expression classes in System.Text.RegularExpressions use the
Reflection.Emit library to generate a custom matching engine for each regular expression compiled.
11. Pointers and Unsafe Code
Although core C# is like Java in that there is no access to a pointer type that is analogous to pointer
types in C and C++, it is possible to have pointer types if the C# code is executing in an unsafe context.
When C# code is executing in an unsafe context, a lot of runtime checking is disabled which means
that the program must have full trust on the machine it is running on.
Certain situations call for the use of unsafe code such as when interfacing with the underlying
operating system, during interactions with COM objects that take structures that contain pointers,
when accessing a memory-mapped device or in situations where performance is critical. The syntax
and semantics for writing unsafe code is similar to the syntax and semantics for using pointers in C
and C++. To write unsafe code, the unsafe keyword must be used to specify the code block as unsafe
and the program must be compiled with the /unsafe compiler switch.
Since garbage collection may relocate managed (i.e. safe) variables during the execution of a program,
the fixed keyword is provided so that the address of a managed variable is pinned during the execution
of the parts of the program within the fixed block. Without the fixed keyword there would be little
purpose in being able to assign a pointer to the address of a managed variable since the runtime may
move the variable from that address as part of the mark & compact garbage collection process.
C# Code
using System;
class UnsafeTest{
Sort(iptr, array.Length);
}//fixed
Console.WriteLine("\nSorted Array:");
foreach(int x in array)
Console.Write(x + " ");
61 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
}
}
62 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
63 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
C# Code
using System;
class CheckedTest{
64 of 77
model;
make;
year;
name;
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
=
=
=
=
name;
model;
make;
year;
void IRobot.IdentifySelf(){
Console.WriteLine("My name is " + this.name);
}
void IVehicle.IdentifySelf(){
Console.WriteLine("Model:" + this.model + " Make:" + this.make + " Year:" + this.year);
}
= (IRobot) tr;
v.IdentifySelf();
r.IdentifySelf();
}
}
OUTPUT
Model:Toyota Make:Corolla Year:2001
My name is SedanBot
65 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
NOTE: The extern alias statement can be used to attach an alias to an assembly which can then be used
as the left operand of the :: operator. When this is done the scope used for name resolution is the top
level namespace(s) within the assembly.
18. Iterators (Continuations)
For a data structure to support being a target of the foreach loop it must implement or return an
instance of System.Collections.IEnumerable. However writing an Enumerator can be somewhat cumbersome
which is where the yield keyword comes in. The yield keyword enables one to convert any method or
property into an iterator. In an iterator, one simply traverses the data structure and returns its
contents one by one using the yield return statement and indicates the end of the sequence of values
with the yield break statement. The method or property must return one of IEnumerable,
66 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
67 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
It should be noted that all of the class attributes are merged across all denitions of a class. This
means that contradictory attributes (e.g. class declared as private in one le and public in another) are
disallowed.
20. Static Classes
A static class is a class that has no instance members, no instance constructors and cannot be used as
a base class. A static class should be used to dene types for which instances don't make sense such as
the System.Environment and System.Math classes.
A static class is specied by prexing the class declaration with the keyword
static.
C# Code
using System;
public static class StaticClass{
public static void HelloWorld(){
Console.WriteLine("Hello World");
}
}
public class Test{
public static void Main(string[] args){
StaticClass.HelloWorld();
}
}
68 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
int? x = 5;
if(x.HasValue){
Console.WriteLine("The value of x is " + x.Value);
}
x = null;
//prints 0
Console.WriteLine(x.GetValueOrDefault());
}
}
The ?? operator is called the null coalescing operator and is used for testing the value of a nullable
type and returning its value or an alternate if its value is null. Thus x ?? y is equivalent to x == (null
: x).
? y
C# Code
using System;
public class Test{
public static void Main(string[] args){
int? x = null;
int y = x ?? 5;
//prints 5
Console.WriteLine(y);
}
}
69 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
There are a number of restrictions to anonymous methods that must be kept in mind. For one, jump
statements like break, goto and continue cannot be used o jump into an anonymous method from outside
the code block or vice versa. Also anonymous methods cannot refer to ref or out parameters that are
dened outside the scope of the method.
In C#, all exceptions are unchecked and there is no analog to the throws clause. One major side eect
of this is that unless the creator of the API explicitly documents the exceptions thrown then it is not
possible for the users of the API to know what exceptions to catch in their code leading to unrobust
applications that can fail unexpectedly. Thus users of C# are reliant on the documentation skill of
programmers as their primary error handling mechanism which is a less than optimal situation.
For instance in the following code snippet, the only way to know what exceptions can be thrown by the
method below is to either have the source code for all the methods called within it or if the developer
of the method documents all the exceptions thrown by all the methods called within it (meaning that
the developers of those methods must have done the same ad innitum).
C# Code
70 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
The above code snippet is from the .NET Framework Beta 2 documentation for the Socket class. Note
how there no exceptions caught in the code. If this was a method in a real application as opposed to a
sample, it would be impossible for the users of this method to know what exceptions to catch without
access to the source code or without the author of the method painstakingly checking what exceptions
are thrown by every single method called and then documenting them. Below is the list of exceptions
that could be thrown within the method according to their entries in the Microsoft .NET framework
Beta 2 documentation.
Method
Exception(s) thrown
Encoding.GetBytes
ArgumentNullException
Dns.Resolve
ArgumentNullException, SocketException
SocketException
Socket.Connect
ArgumentNullException, SocketException
Socket.Receive
ArgumentNullException, SocketException
ASCII.GetString
[undocumented as of Beta 2]
If the author of the method does not have time to document the exceptions that may be thrown from
this method or happens to leave out an important one, such as the SocketException in this case, then
71 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
the users of the method could have their applications fail unexpectedly without an elegant means of
recovery in place. In the above case, the main exception of interest to users would probably be the
SocketException since the others are all related to the internal workings of the method and don't
really have anything to do with the caller and in fact would probably be unchecked exceptions if they
existed in Java. In practice the GetMessageFromServer method would check the validity of its string
parameter and throw ArgumentNException or one of its subclasses depending the results of the check.
The rationale for excluding checked exceptions from C# has never been fully explained by Microsoft
but this message from Eric Gunnerson of the C# team sheds some light on the reasoning behind this
decision. The primary reason for this choice according to Gunnerson is that examination of small
programs led to the conclusion that using checked exceptions could both enhance developer
productivity and enhance code quality. On the other hand experience with large software projects
suggested that using checked exceptions decreased productivity with little or no increase in code
quality.
[updated 12/5/2001] It should be noted that there is agreement amongst some Java developers with
Eric Gunnerson's assertion that checked exceptions have certain disadvantages. Alan Griiths wrote
an excellent article entitled Exceptional Java where he notes that checked exceptions lead to breaking
encapsulation, loss of information and information overload. Bruce Eckel, author of Thinking In Java
and Thinking In C++, also questions the wisdom of checked exceptions in his article entitled Does Java
need Checked Exceptions?.
The lack of checked exceptions in C# will be very unsettling for Java developers and may lead to
program designs which are awed. One only has to remember the anecdote about how originally a
considerable amount of the exceptions in the Java API were unchecked but upon changing them to
checked exceptions a number of bugs and design aws were found in the API. Hopefully this will be
remedied in later versions of C# or a third party could develop a static source code analysis tool such
as lint. Meanwhile C# developers must take care to document all exceptions thrown from their
methods that callers should be aware of as a matter of consideration. This is not to say that
documentation should not typically exist but since it is the only means to ensure exception safe C#
code then its importance is now a much greater.
2. Cross Platform Portability (Write Once, Run Anywhere)
A major selling point of Java technologies is that applications written in Java are portable across a
number of operating systems and platforms. Sun oicially supports Linux, Windows and Solaris but
other vendors have implemented Java on a large range of platforms including OS/2, AIX and MacOS.
Binary compatibility across platforms using similar Java versions is the norm except for situations
involving bugs in various VM implementations.
At the time of this writing C# is only available on Windows. Eorts are currently in place to port it to
other platforms, including Linux and FreeBSD. Linux porting is being done as part of the Mono project
developed by Ximian while the FreeBSD implementation is a Microsoft project codenamed rotor.
3. Extensions
The Java extension mechanism enables developers to extend the abilities of the core Java platform.
Developers can create classes and packages which are treated by the Java runtime as if they are core
Java classes and packages like java.lang, java.util, java.net,etc. This means that extensions do not have
to be placed on the class path since they are treated as if they are part of the core libraries such as
those in the Java runtime library, rt.jar. Extensions are contained within JAR les and once installed
are available to all applications running on the target platform.
A C# parallel would be the ability to create assemblies that are treated as if they are part of the
namespace contained in the System.dll assembly.
System
4. strictfp
In Java,
72 of 77
strictfp
is a modier that can be used for class, method or interface declarations to ensure
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
strict oating point arithmetic that conforms to behavior specied in the IEEE standard 754 for binary
oating-point arithmetic (IEEE 754). Within an FP-strict expression, all intermediate values must be
members of the oat or double value set, depending on whether the expression is evaluating oats or
doubles. Within expressions that are not FP-strict, it is allowable for the JVM implementation to use an
extended exponent range to represent intermediate results. The example below claries the dierence
between FP-strict and non-FP-strict expressions.
Java Code
public class FPTest {
static strictfp double halfOfSquareFP(double n){
return n * 4.0
}
* 0.5;
In the above example the value printed by calling halfOfSquareFP() will be "Innity" regardless of
what JVM the application is run on. This is because Java enforces left-to-right evaluation of arguments
and 6.6e+307 multiplied by 4.0 exceeds the maximum value for a double thus leading to all subsequent
operations yielding Innity. On the other hand the value printed on calling halfOfSquareNFP() may not
be the same on dierent JVMs depending on whether the target platform and JVM implementation
support storing intermediate values in an extended format that has a larger range than that of doubles.
Thus on some platforms the value 1.32E308 is printed as the value returned by halfOfSquareNFP() while
on others "Innity" is printed.
Section 4.1.5 of the C# specication covers oating point numbers and states that due to the excessive
performance costs of enforcing that certain architectures perform operations with less precision than
is possible, there is no way to enforce FP-strictness in C#.
5. Dynamic Class Loading
The ability to dynamically load classes at runtime in Java is a very powerful feature especially when
combined with a remote procedure call mechanism. Dynamic class loading enables Java applications to
download the class les (i.e. byte codes) of classes that do not exist on the target machine. An object
type that only exists on one machine can be transferred to other machines in a seamless and
transparent manner. Thus new types can be introduced on a remote machine which allows the
behavior of remote applications to be signicantly extended at runtime. The following example shows
an example of a remote application that accepts types that implement a certain interface, IStockTicker.
Java Code
public class MyRMIServer extends UnicastRemoteObject
implements SomeInterface {
public MyRMIServer() throws RemoteException{ super();}
73 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
if(stock_ticker.equalsIgnoreCase("MSFT"))
return "Microsoft Corporation";
else if(stock_ticker.equalsIgnoreCase("SUNW"))
return "Sun Microsystems";
else
return "Unknown Stock Ticker";
}/* obtainName(IStockTicker) */
}
The obtainName() remote method in the above class accepts types that implement the IStockTicker
interface. It is possible for this method to be invoked from a remote client which then passes a type
that implements IStockTicker, for example NASDAQStock, that does not exist on the server where the
MyRMIServer class lives. In this case the entire code needed for NASDAQStock class is transmitted
from the client to the remote server automatically.
C# and the .NET Remoting mechanism also enable remotely downloading classes from one machine to
the other but the client has to publish the assembly and the server can then load it via a URL.
For information on Java Remote Method Invokation (RMI) read the Java tutorial on RMI. Information
on .NET Remoting with C# is explained in this introduction to .NET remoting and this technical
overview on MSDN.
6. Interfaces That Contain Fields
In Java it is possible for constants to be declared in interfaces which are then available to
implementing classes while in C# this is not allowed. This may not be a big issue in C# since the
primary usage of constants declared in interfaces is as a poor emulation of enumerations.
7. Anonymous Inner Classes
An anonymous inner class is a class declaration that occurs at the same point where an instance of
that class is created. Anonymous inner classes are typically used where only one instance of a type will
exist in the application. The most popular usage of anonymous inner classes is for specifying callbacks
especially in the Java GUI libraries but there are other situations where anonymous inner classes are
benecial as well. Below is an example of using anonymous inner classes to implement the State
Design Pattern.
Java Code
/* An instance of this class represents the current state of a ClientView GUI. */
public abstract class ClientState{
// This instance of the class is used to signify that the user is not logged in.
// The only thing a user can do in this state is login and exit.
public static ClientState NOT_LOGGED_IN = new ClientState() {
public void setMenuState(ClientView cv) {
cv.setMenuEnabledState(false); /* disable all menus */
cv.menuLogin.setEnabled(true);
cv.menuExit.setEnabled(true);
//can't type
cv.textArea.setEnabled(false);
}
public String toString(){
return "ClientState: NOT_LOGGED_IN";
}
};
74 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
// This instance of the class is used to signify that the user is logged in
// but has not yet created a document to work with. The user cannot type or save
// anything in this mode.
public static ClientState NO_OPEN_DOCUMENT = new ClientState() {
public void setMenuState(ClientView cv) {
cv.setMenuEnabledState(false); /* disable all menus */
cv.menuLogin.setEnabled(true);
cv.menuExit.setEnabled(true);
cv.menuOpenFile.setEnabled(true);
cv.menuNewFile.setEnabled(true);
//can't type
cv.textArea.setEnabled(false);
}
public String toString(){
return "ClientState: NO_OPEN_DOCUMENT";
}
};
// This instance of the class is used to signify that the user is editting a file.
// In this mode the user can use any functionality he/she sees fit.
public static ClientState EDITTING_DOCUMENT = new ClientState() {
public void setMenuState(ClientView cv) {
cv.setMenuEnabledState(true);
cv.textArea.setEnabled(true);
}
Below is an example of the code that would utilize the above ClientState class.
bool loginUser(String username, String passwd) {
//check if already logged in
if(myGUI.state == ClientState.NOT_LOGGED_IN)
return true;
//enable parts of the GUI if the user authenticates
if(userAuthenticated(username, passwd)){
myGUI.state = ClientState.NO_OPEN_DOCUMENT;
myGUI.state.setMenuState(myView);
return true;
}
return false;
75 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
8. Static Imports
The static import feature makes it possible to access static members of a class without having specify
the class name. This feature is intended to reduce the verbosity of code that frequently access the
static members of a particular class (e.g. constants dened in a particular helper class).
A static import similar to a regular import statement except that the keyword
of importing a package, a specic class is imported.
static
Java Code
import static java.awt.Color.*;
public class Test{
public static void main(String[] args) throws Exception{
//constants not qualified thanks to static import
System.out.println(RED + " plus " + YELLOW + " is " + ORANGE);
}
}
Conclusion (2001)
Most developers, especially those with a background in C or C++, would probably agree that features like
operator overloading, pointers, preprocessor directives, delegates and deterministic object cleanup make
C# more expressive than Java in a number of cases. Similarly, Java developers who learn C# will be
pleasantly surprised at features that are missing in Java that will seem glaring in their absence once one
uses them in C#, such as boxing, enumerations and pass by reference. On the other hand the lack of
checked exceptions, inner classes, cross platform portability or the fact that a class is not the smallest unit
of distribution of code makes the choice of C# over Java not a clearcut case of choosing more language
features without having to make any compromises.
It is my opinion that both languages are similar enough that they could be made to mirror each other
without signicant eort if so required by either user base. In this case, C# would have it easier than Java
in that C# has less to borrow from Java than Java would have to borrow from C#. However, the true worth
of a programming language that is intended for use outside of academia is how quickly the language
evolves to adapt to the changing technological landscape and what kind of community surrounds the
language. Some programming languages are akin to the French language under the Les Immortels of the
Acadmie Franaise in France. Les immortels are charged with dictating what constitutes the oicial
French language but they have been slow to adapt to the information age thus their edicts on what
constitutes the proper French versions of new words, especially those related to technology, are usually
ignored especially since they either conict with what the general French public would rather call them and
show up long after the unsanctioned words have already entered the lexicon. C++ is an example of a
language that has undergone a process of balkanization closely resembling the French language under the
Les Immortels of the Acadmie Franaise while Java under Sun Microsystems can be considered to be a
language that has evolved with the times similar to how the English language has done.
Thus the question really becomes, which of these languages looks like it will evolve with the times and be
easiest to adapt to new situations as they arise? So far, Sun has done a great job with Java although a lack
of versioning support and the non-existence of a framework that enables extensibility of the language built
into the platform makes drastic evolution diicult. C# with its support for versioning via the .NET
framework and the existence of attributes which can be used to extend the features of the language looks
like it would in the long run be the more adaptable language. Only time will tell however if this prediction is
76 of 77
04/05/2016 10:56 AM
http://www.25hoursaday.com/CsharpVsJava.html...
accurate.
Conclusion (2007)
As predicted in the original conclusion to this paper, a number of features have become common across
both C# and Java since 2001. These features include generics, foreach loops, enumerations, boxing,
variable length parameter lists and metadata annotations. However after years of convergence it seems
that C# and Java are about to go in radically dierent directions. The current plans for C# 3.0 are
highlighted in the Language Integrated Query (LINQ) Project which encompasses integrating a number of
data oriented features including query, set operations, transformations and type inferencing directly into
the C# language. In combination with some of C#'s existing features like anonymous methods and nullable
types, the dierences between C# and Java will become more stark over the next few years in contrast to
the feature convergence that has been happening over the past few years.
Resources
1. Eckel, Bruce. Thinking In Java. Prentice Hall, 2000.
2. Gunnerson, Eric. A Programmer's Introduction To C#. Apress, 2001.
3. Sun Microsystems. The Java Tutorial.<http://java.sun.com/docs/books/tutorial/>
4. Microsoft Corporation. .NET Framework Programming. < http://msdn2.microsoft.com/en-us/library
/ms229284(VS.80).aspx>
5. Microsoft Corporation. C# Language Reference. < http://msdn2.microsoft.com/en-us/library
/618ayhy6(VS.80).aspx>
Acknowledgements
The following people helped in reviewing and proofreading this article: Paul Johns, David Dagon, Dr. Yannis
Smaragdakis , Dmitri Alperovitch, Dennis Lu and Sanjay Bhatia.
2001, 2007 Dare Obasanjo
77 of 77
04/05/2016 10:56 AM