The Full Wiki

Comparison of Java and C Sharp: Wikis

Advertisements
  

Note: Many of our articles have direct quotes from sources you can cite, within the Wikipedia article! This article doesn't yet, but we're working on it! See more info or our list of citable articles.

Encyclopedia

From Wikipedia, the free encyclopedia

Programming language comparisons
General comparison
Basic syntax
Basic instructions
Arrays
Associative arrays
String operations
String functions
List comprehension
Object-oriented programming
Metaprogramming
Object-oriented constructors
Database access
Database RDBMS
Evaluation strategy
List of "hello world" programs

ALGOL 58's influence on ALGOL 60
Comparison of ALGOL 68 and C++
ALGOL_68: Comparisons with other languages
Compatibility of C and C++
Comparison of Pascal and Borland Delphi
Comparison of Pascal and C
Comparison of Java and C++
Comparison of Java and C#
Comparison of C# and Visual Basic .NET

Contents

Introduction

This is a comparison of the C# programming language with the Java programming language. While the focus of this article is mainly the programming languages and their features, such a comparison will necessarily also consider some platform features and some library features. Neither Java nor C# can be evaluated without taking the respective platforms and libraries into consideration.

The comparison will naturally focus on the areas where the languages differ. This may skew the fact that the two languages and their platforms are actually more alike than they are different: Both are (primarily) statically, strongly and explicitly typed, both are class-based object-oriented, both are designed with semi-interpretation or runtime compilation in mind, both use garbage-collected memory models and both are considered "curly brace" C/C++ style languages. The common ancestry is also evident in the fact that common concepts are often termed the same way and more often than not have very similar syntax.

Platforms

Java (the programming language) is designed to execute on the Java platform, the Java Runtime Environment (JRE). The runtime environment includes the Java Virtual Machine (JVM) as well as a common set of libraries. C# is designed to execute on the Common Language Runtime (CLR).

The official Sun JRE is available for: [1]

  • Solaris (32bits/64bits)
  • Windows (32bits/64bits)
  • Linux (32bits/64bits)

Other JRE include:

  • Mac OS: Apple Computer supplies their own version of Java.[2]
  • Google Android: Google Android for smartphones also make heavy use of Java.
  • Light versions of the JRE, like the J2ME can also be found on most mobile phones. [3]

The official Microsoft CLR is available for:

  • Windows (32bits/64bits)

Other CLR include:

  • A partial port of the CLR named Mono (software) is also underway for the Linux operating system, though it suffers a lot of criticism, especially from Free Software activists. [4]
  • Light versions of the CLR are also available to Windows Mobile smartphones.

Language

Advertisements

Object handling

Both C# and Java are designed from the ground up as object oriented languages using dynamic dispatch, with syntax similar to C++ (C++ in turn is derived from C). Neither language is a superset of C or C++, however. Both mainly use garbage collection as a means of reclaiming memory resources, rather than explicit deallocation of memory (though C# requires explicit deallocation for graphical, GDI+ objects, in which case it uses the IDisposable interface). Both include thread synchronization mechanisms as part of their language syntax.

In both languages objects are created with a new.

References

In both languages references are a central concept. All instances of classes are by reference.

While not directly evident in the language syntax per se, both languages support the concept of weak references. An instance which is only referenced by weak references is eligible for garbage collection just as if there were no references at all. In both languages this feature is exposed through the associated libraries, even though it is really a core runtime feature.

In addition to weak references, Java has soft references. Soft references are much like weak references, but the JVM will not deallocate softly-referenced objects until the memory is actually needed.

feature Java C#
Garbage collection Yes Yes
Deterministic disposal No Yes
Weak references Yes Yes
Soft references Yes No
Object pinning (fixed to address throughout lifetime) No Yes

Pointers

C# allows use of pointers and corresponding pointer arithmetic. Pointers and pointer-arithmetic are potentially unsafe in a managed environment as they can be used to bypass the strict rules for object access. C# addresses that concern by requiring that code blocks or methods that use the feature be marked with the unsafe keyword, so that all clients of such code can be aware that the code may be less secure than otherwise. The compiler requires the /unsafe switch to allow compilation of a program that uses such code. Generally, unsafe code is either used to allow better interoperability with unmanaged APIs or system calls (which are inherently "unsafe"), or for performance reasons. For safety reasons, Java does not allow pointers or pointer-arithmetic to be used at all.

Object initialization

In both C# and Java, object's fields can be initialized either by variable initializers (expressions that can be assigned to variables where they are defined) or by constructors (special subroutines that are executed when an object is being created). In addition, Java knows the so called instance initializers, which are block with similar function than constructors, except that they contain no code.

In C#, object fields are initialized in the fllowing order when an object is created:

  1. Derived static fields
  2. Derived static constructor
  3. Derived instance fields
  4. Base static fields
  5. Base static constructor
  6. Base instance fields
  7. Base instance constructor
  8. Derived instance constructor

Some of the above fields may not be applicable (e.g. if an object does not have static fields). Derived fields are those that are defined in the object's direct class while base fields is a term for the fields that are defined in one of the object's superclasses. Note that an object representation in memory contains all fields defined in its class or any of its superclasses, even if some fields in superclasses are defined as private.

It is guaranteed that any field initializers take effect before any constructors are called, since both instance constructor of the object's class and its super classes are called after field initializers are called. There is, however, a potential trap in object initialization when a virtual method is called from a base constructor. The overriden method in a subclass may reference a field that is defined in the subclass, but this field may not been initialized because the cubclass' constructor that contains field initialization is called after the constructor of its base class.

In Java, the order of initialization is as follows:

  1. Invocation of another constructor (either of the object's class or of object's superclass)
  2. Instance variable initializers
  3. The constructor body

Like in C#, a new object is created by calling a specific constructor. Within a constructor, the first statement may be invocation of another constructor. If this is omitted, the call to the super class' argument-less constructor is added implicitly by the compiler. Otherwise, either another overloaded constructor of the object's class can be called explicitly, or a superclass' constructor can be called. In the former case, the the called constructor will again call another constructor (either of the object's class or its cubclass) and the chain sooner or later ends up at the call to one of the superclass' constructor.

After another constructor is called (which causes direct invocation superclass' constructor, and so forth, down to the Object class), instance variables defined in the object's class are initialized. Even if there are no variable initializers explicitly defined for some variables, these variables are initialized to default values. Note that instance variables defined in superclasses are already initialized by this point, because they were initialized by superclass' constructor when it was called (either by constructor's code or by variables' initializers performed before constructor's code or implicitly to default values). In Java, variable initializers are executed according to their textual order in the source file.

Finally, the constructor body is executed. This ensures proper order of initialization, i.e. base class' fields are initialized before initialization of object class' fields begins.

There are two main potential traps in Java's object initialization. First, variable initializers are expressions that can contain method calls. Since methods can reference any variable defined in the class, the method called in variable's initializer can reference a variable that is defined below the variable being initialized. Since initialization order corresponds to textual order of variable definitions, such a variable would not be initialized to the value prescribed by its initializer and would contain the default value. Another potential trap is when a method that is overridden in the derived class is called in the base class' constructor, which can lead to behavior the programmer would not expect when object of the derived class is created. According to initialization order, the body of the base class' constructor is executed before variable initializers are evaluated and before the body of the derived class' constructor is executed. The overridden method called form the base class' constructor can however reference variables defined in the derived class, but these are not yet initialized to the values specified by their initializers or set in derived class' constructor.

Data types

feature Java C#
Signed integer types (bit widths) 8,16,32,64 8,16,32,64
Unsigned integer types (bit widths) only 16 (char) 8,16,32,64
IEEE floating point types (bit sizes) 32,64 32,64
Large decimal support (financial) First party library[5] Language built-in[6]
Arbitrary-precision arithmetic type Yes[5] Yes
Strings and characters immutable reference type, unicode immutable reference type, unicode
Date/time type mutable reference type value type
Boolean Yes Yes
Fixed-length strings No Yes


Both languages support the idea of primitive types which are all value types in C#/.NET, except for String which is a reference type. C# has more primitive types than Java, with unsigned as well as signed integer types being supported, and a decimal type for decimal floating-point calculations. Java lacks unsigned types. In particular, Java lacks a primitive type for an unsigned byte, while C# bytes are unsigned by default. Strings are treated as (immutable) objects in both languages, but support for string literals provides a specialized means of constructing them. C# also allows verbatim strings for quotation without escape sequences, which also allow newlines.

Both allow automatic boxing and unboxing to translate primitive data to and from their object form. Effectively, this makes the primitive types a subtype of the Object type. In C# this also means that primitive types can define methods, such as an override of Object's ToString() method. In Java, separate primitive wrapper classes provide such functionality. In Java primitive values are not implicitly boxed when dereferenced and an explicit cast is required for an instance call on a primitive value — ((Integer)42).toString() instead of a C# instance call 42.ToString(). Another difference is that Java makes heavy use of boxed types in generics (see below), and as such allows an implicit unboxing conversion (in C# this requires a cast). As these implicit unboxing conversions can potentially throw null pointer exceptions, modern integrated development environments and compilers can be configured to highlight them.

Value types

C# allows the programmer to create user-defined value types, using the struct keyword. From the programmer's perspective, they can be seen as lightweight classes. Unlike regular classes, and like the standard primitives, such value types are passed by value rather than by reference. They can also be part of an object (either as a field or boxed), or stored in an array, without the memory indirection that normally exists for class types. Structs also come with a number of limitations. Because structs have no notion of a null value and can be used in arrays without initialization, they always come with an implicit default constructor that essentially fills the struct memory space with zeroes. The programmer can only define additional constructors with one or more arguments. This also means that structs lack a virtual method table, and because of that (and the fixed memory footprint), they cannot allow inheritance (but can implement interfaces). Java does not include the concept of value types.

Enumerations

Enumerations in C# are derived from a primitive integer type (8, 16, 32, or 64 bit). Any value of the underlying primitive type is a valid value of the enumeration type, though an explicit cast may be needed to assign it. C# also supports bitmapped enumerations where an actual value may be a combination of enumerated values bitwise or'ed together.

Enumerations in Java, on the other hand, are full objects. The only valid values are the ones listed in the enumeration. Also, as objects, each enumeration can contain its own methods and fields, like a dedicated toString() method, for instance, or comparators. They can be considerered classes with a predefined amount of instances, which are the enum constants. Special enumeration set and map collections provide fully type-safe functionality with minimal overhead.

Both C# and Java enumerations can be converted to strings and can be used in a switch statement.

Arrays

Array and collection types are also given significance in the syntax of both languages, thanks to an iterator-based foreach statement loop. In C# an array corresponds to an object of the Array class, while in Java each array is a direct subclass of the Object class (but can be cast to an array of an element type that is an ancestor of its true element type), and does not implement any of the collection interfaces. C# has true multidimensional arrays, as well as the arrays-of-arrays that are available in Java (and which in C# are commonly called jagged arrays). Multidimensional arrays can in some cases increase performance because of increased locality (as there is a single pointer dereference, instead of one for every dimension of the array as is the case for jagged arrays). Another advantage is that the entire multidimensional array can be allocated with a single application of operator new, while jagged arrays require loops and allocations for every dimension. Note, though, that Java provides a syntactic construct for allocating a multidimensional jagged array with regular lengths (a rectangular array in C# terminology); the loops and multiple allocations are then performed by the virtual machine and need not be explicit at the source level.

Inner classes

Both languages allow inner classes, where a class is defined lexically inside another class. However, in each language these inner classes have rather different semantics.

In Java, unless the inner class is declared static, a reference to an instance of an inner class carries a reference to the outer class with it. As a result, code in the inner class has access to both the static and non-static members of the outer class. To create an instance of a non-static inner class, one has to name the instance of the embracing outer class [7]. This is done via a new new-operator introduced in JDK 1.3: outerClassInstance.new Outer.InnerClass(). This can be done in any class that has a reference to an instance of the outer class.

In C#, an inner class is conceptually the same as a normal class. In a sense, the outer class only acts as a namespace. Thus, code in the inner class cannot access non-static members of the outer class unless it does so through an explicit reference to an instance of the outer class. The inner class can be declared private to allow only the outer class to have any access to it.

Java provides another feature called local classes or anonymous classes, which can be defined within a method body. These are generally used to implement an interface with only one or two methods, which are typically event handlers. They can also be used to override virtual methods of a super-class however. The methods in those local classes have access to the outer method's local variables declared final. C# satisfies the use-cases for these by providing anonymous delegates; see event handling for more about this.

C# also provides a feature called anonymous classes, but it is rather different from Java's concept with the same name. It allows the programmer to instantiate a class by providing only a set of names for the properties the class should have, and an expression to initialize each. The types of the properties are inferred from the types of those expressions. These implicitly-declared classes derived directly from object.

Partial classes

C# allows a class definition to be split across several source files using a feature called partial classes. Each part must be marked with the keyword partial. All the parts must be presented to the compiler as part of a single compilation. Parts can reference members from other parts. Parts can implement interfaces and one part can define a base class. The feature is useful in code generation scenarios (such as UI design) where a code generator can supply one part and the developer another part to be compiled together. The developer can thus edit their part without the risk of a code generator overwriting that code at some later time. Unlike the class extension mechanism a partial class allows "circular" dependencies amongst its parts as they are guaranteed to be resolved at compile time. Java has no corresponding concept.

Generics

feature Java C#
Type compilation Type erasure Reified
co-variance use-site limited, use-site
contra-variance use-site no (yes in .net 4.0)
type parameter static members no yes
static scope shared among all generic realizations separate for each generic realization
array component types limited all types

Both languages now support generics programming, but they have taken different paths to its implementation.

Generics in Java are a language-only construction; they are implemented only in the compiler. The generated classfiles include generic signatures only in the form of metadata (allowing the compiler to compile new classes against them). The runtime has no knowledge of the generic type system, which meant that JVM implementations only needed minimal updates to handle the new class format.

To achieve this goal the compiler replaces all generic types by their upper bounds and inserts casts appropriately in the various places where the type is used. The resulting byte code will contain no references to any generic types or parameters. This technique of implementing generics is known as type erasure. This means that information about the actual types is not available at runtime, and imposes some restrictions such as the inability to create new instances or arrays of generic type arguments. (See also Generics in Java.)

C# took a different route. Support for genericity was integrated into the virtual execution system itself and first appeared in .NET 2.0. The language then becomes merely a front-end for the underlying generics support in the execution system. As in Java, the compiler provides static type safety checking, but additionally the JIT performs load time verification of the correctness, at a very minimal performance cost. Information on generic types is fully preserved at runtime, and allows complete reflection support as well as instantiation of generic types.

C# allows generics directly for primitive types. Java, instead, allows the use of boxed types as type parameters (e.g., List<Integer> instead of List<int>), but this comes at a small cost since all such values need to be heap-allocated (however, a generic type can be specialized with an array type of a primitive type in Java, for example List<int[]> is allowed). [8]

Notation and special features

Special feature keywords

keyword feature, example usage
checked, unchecked In C#, checked statement blocks or expressions can enable run-time checking for arithmetic overflow.
get, set C# implements properties as part of the language syntax with their optional corresponding get and set accessors, as an alternative for the accessor methods used in Java, which is not a language feature but a coding pattern based on method name conventions.
goto C# supports the goto keyword. This can occasionally be useful, for example for implementing finite state machines or for generated code, but the use of a more structured method of control flow is usually recommended (see criticism of the goto statement). Java allows labeled breaks and continues, which make up for many of the uses of goto.
switch(color)
{
    case Color.Blue:
         Console.WriteLine("Color is blue"); break;
    case Color.DarkBlue:
         Console.WriteLine("Color is dark");
         goto case Color.Blue;
    // ...
}
out, ref C# has support for output and reference parameters. These allow returning multiple output values from a method, or passing values by reference.
strictfp Java uses strictfp to guarantee the results of floating point operations remain the same across platforms.
switch In C#, the switch statement also operates on strings and longs but only allows fallthrough for empty statements. Java switch statement does not operate on strings nor long primitive type but falls through for all statements (excluding those with 'break').
throws Java requires every method to declare the checked exceptions or superclasses of the checked exceptions that it can throw. Any method can also optionally declare the unchecked exception that it throws. C# has no such syntax.
public int readItem() throws java.io.IOException
{
    // ...
}
using C#'s using causes the Dispose method (implemented via the IDisposable interface) of the object declared to be executed after the code block has run or when an exception is thrown within the code block.
// Create a small file "test.txt", write a string, 
// ... and close it (even if an exception occurs)
using (StreamWriter file = new StreamWriter("test.txt"))
{
    file.Write("test");
}
yield C# allows the use of the yield keyword to express iterator generators. In Java, iterators can be defined only using (possibly anonymous) classes, requiring considerably more Boilerplate code. Below is an example of an iterator that takes an iterable input (possibly an array) and returns all even numbers.
public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
{
    foreach (int i in numbers)
    {
        if (i % 2 == 0)
            yield return i;
    }
}

Callbacks and Event handling

C# implements object oriented method pointers in the form of delegates. A delegate is a special type which can capture a reference to an instance or static method if its signature is compatible. Multicast-delegates are called events (see below). Delegates provide support for event-driven programming. They are type-safe references to methods and can be combined to allow multicasting. To support them there is a special syntax to define events in classes and operators to register, unregister or combine event handlers. Delegates support covariance and contravariance, and can be created as anonymous methods with full-featured closure semantics. In .NET, closures and anonymous delegates are syntactic sugar.[9][10]

Java does not have a language-level construct like the C# delegate, but use plain Object Oriented design, the observer[11]. Anonymous inner classes are commonly used to implement the listener, allowing you to define the body of the class and create an instance of it in a single point in the code.

Java anonymous classes has been seen by some as syntactic sugar.[citation needed]

With C# delegates it is possible to call either static methods or methods with different names. Observer pattern does not provide that feature because an interface is necessary.

Numeric applications

To adequately support applications in the field of mathematic and financial computation, several language features exist.[12] In this category, Java provides the strictfp keyword, that enables strict floating-point calculations for a region of code. This will ensure that calculations return the exact same result on all platforms. C# provides no equivalent, but does provide the built-in decimal type, for accurate decimal floating-point calculations. This forgoes the problems that exist with binary floating-point representations (float, double). Such binary representations are not suited to accurately represent decimal numbers and hence introduce rounding errors. For financial applications, an accurate decimal type is essential.

The BigDecimal class also provides such characteristics for Java. BigDecimal and BigInteger are types provided with Java that allow arbitrary-precision representation of numbers. The current stable release of the .NET framework (3.5 SP1) does not currently include such classes, but upcoming version 4 will finally add the feature (see Arbitrary-precision arithmetic).

In Java there is no way to provide the same level of integration for library-defined types such as BigDecimal or complex numbers as there is for the primitive types. For this purpose, C# provides the following:

  • Operator overloading and indexers providing convenient syntax (see below).
  • Implicit and explicit conversions; allow conversions such as exist for the built-in int type that can implicitly convert to long.
  • Valuetypes and generics based on valuetypes; in Java every custom type must be allocated on the heap, which is detrimental for performance of both custom types and collections.

In addition to this, C# can help mathematic applications with the checked and unchecked operators that allow to enable or disable run-time checking for arithmetic overflow for a region of code. It also offers rectangular arrays, that have advantages over regular nested arrays for certain applications.[12]

Operator overloading

C# includes a large number of notational conveniences over Java, many of which, such as operator overloading and user-defined casts, are already familiar to the large community of C++ programmers. It also has "Explicit Member Implementation" which allows a class to specifically implement methods of an interface, separate to its own class methods, or to provide different implementations for two methods with the same name and signature inherited from two base interfaces.

Java does not include operator overloading nor "Explicit Member Implementation" in order to prevent abuse of the feature, and to keep the language simple.[13].

C# also includes indexers which can be considered a special case of operator overloading (like C++ operator[]), or parametrized get/set properties. An indexer is a property named this[] which uses one or more parameters (indexes); the indices can be objects of any type:

myList[4] = 5;
string name = xmlNode.Attributes["name"];
orders = customerMap[theCustomer];

Java does not include indexers. The common Java pattern is to write explicit get_ and set_ methods where a C# programmer would use an indexer.

Methods

Methods in C# are non-virtual by default, and have to be declared virtual explicitly if desired. In Java, all non-static non-private methods are virtual. Virtuality guarantees that the most recent override for the method will always be called, but incurs a certain runtime cost on invocation as these invocations cannot be normally inlined, and require an indirect call via the virtual method table. However, some JVM implementations, including the Sun reference implementation, implement inlining of the most commonly called virtual methods.

In Java methods are virtual by default (although they can be "sealed" by using the final modifier to disallow overriding). There is no way to let derived classes define a new, unrelated method with the same name.

This means that by default in C#, and only when explicitly asked in Java, you can define new methods in a derived class with the same name and signature than the one in its base class. Which implies that when you call that method on such an object, depending on the current knowledge of the caller (if it knows its exact subclass or not), the result will be different.

In Java (by default), the subclass' method will be called, but you will be able to call the base class' own method if needed. In C# (by default), the base class' method will be called, and you won't be able to intercept the call.

In very specific cases, when a base class is designed by a different person, and a new version introduces a method with the same name and signature as some method already present in the derived class, problems can happen.

In Java, this will mean that the method in the derived class will implicitly override the method in the base class, even though that may not be the intent of the designers of either class. Since Java 5.0, a compiler warning will be generated if the special @Override annotation is not added.

To prevent this versioning problem, C# requires that if a method should be overridden, the override keyword must be specified. Otherwise, the method will "hide" the inherited method. A compiler warning to this effect is issued, which can be silenced by specifying the new keyword. This avoids the problem which can arise from a base class being extended with a protected/public method whose signature is already in use by a derived class.

Explicit interface implementation

In either language if a method (or property in C#) is specified with the same name and signature in multiple interfaces, the members will clash when a class is designed which implements those interfaces. An implementation will by default implement a common method for all of the interfaces. If separate implementations are required (because the methods really do serve separate purposes, or because return values differ between the interfaces) C# explicit interface implementation will solve the problem, though allowing different results for the same method, depending on the current cast of the object. In Java there is no way to solve this problem other than cleaning the code and refactoring one or more of the interfaces to avoid name clashes.

Closures

When a reference to a method can be passed around for later execution, a problem arises about what to do when the method has references to variables/parameters in its lexical scope. C# has true closures in which the referenced method can fully capture any variable/parameter from its lexical scope. In Java's anonymous inner classes only references to final members of the lexical scope are allowed, thus requiring the developer to artificially introduce extra levels of indirections and boxing primitive types if he wants to reference and update those from the inner class.

Java does not currently feature closures; however, it has been announced that some form of closures will be included in JDK 7. [14]

In Java, anonymous inner classes remains the preferred way to emulate closures. Aside from being a more verbose construction, this approach also has some drawbacks compared to real closures, such as limited access to variables from the enclosing scopes (only final members can be referenced).

Lambdas and expression trees

C# features a special type of inline closures called lambdas. These are anonymous methods: they have a signature and a body, but no name. They are not methods in that they cannot form part of a class interface. They are mainly used to specify local function-valued arguments in calls to other methods, a technique mainly associated with functional programming. On top of that, lambda functions can double as a way to define special data structures called expression trees. Whether they are seen as an executable function or a data structure depends on compiler type inference and what type of variable or parameter they are assigned/cast to. Lambdas and expression trees play key roles in LINQ. Java does not feature lambdas or expression trees; its primary mechanism for inline scope capture and method definition is the anonymous inner class syntax.

Partial methods

Related to partial classes C# allows partial methods to be specified within partial classes. A partial method is an intentional declaration of a method with a number of restrictions on the signature. These restrictions ensure that if a definition is not actually provided by any class part, then the method and every call to it can be safely erased. This feature allows code to provide a large number of interception points (like the template method GoF design pattern) without paying any runtime overhead if these extension points are not being used by another class part at compile time. Java has no corresponding concept.

Extension methods

Using a special this designator on the first parameter of a method, C# allows the method to act as if it were a member method of the type of the first parameter. This extension of the foreign class is purely syntactical. The extension method needs to be static and defined within a purely static class. It must obey any restriction on such external static methods and thus cannot break object encapsulation. The "extension" is only active within scopes where the namespace of the static host class has been imported. Java has no corresponding concept.

Generator methods

A C# method which is declared as returning IEnumerable, IEnumerator and/or the generic versions of these interfaces (in C#, both the generic and non-generic versions must be implemented at the same time, adding length to the code), can be implemented using yield syntax. This is a form of limited, compiler-generated continuations and can drastically reduce the code required to traverse or generate sequences, although that code is just generated by the compiler instead. The feature can also be used to implement infinite sequences, e.g. the sequence of Fibonacci numbers. Java has no corresponding concept.

Conditional compilation

Unlike Java, C# implements conditional compilation using preprocessor directives. It also provides a Conditional attribute to define methods that are only called when a given compilation constant is defined. This way, assertions can be provided as a framework feature with the method Debug.Assert(), which is only evaluated when the DEBUG constant is defined. Since version 1.4, Java provides a language feature for assertions, which are turned off at runtime by default but can be enabled using the "-enableassertions" or "-ea" switch when invoking the JVM.

Namespaces and source files

C#'s namespaces are similar to those in C++. Unlike package names in Java, a namespace is not in any way tied to location of the source file. While it's not strictly necessary for a Java source file location to mirror its package directory structure, it is the conventional organization.

Both languages allow importing of classes (e.g., import java.util.* in Java), allowing a class to be referenced using only its name. Sometimes classes with the same name exist in multiple namespaces or packages. Such classes can be referenced by using fully qualified names, or by importing only selected classes with different names. To do this, Java allows importing a single class (e.g., import java.util.List). C# allows importing classes under a new local name using the following syntax: using Console = System.Console. It also allows importing specializations of classes in the form of using IntList = System.Collections.Generic.List<int>.

Java has a static import syntax that allows using the short name of some or all of the static methods/fields in a class (e.g., allowing foo(bar) where foo() can be statically imported from another class). C# has a static class syntax (not to be confused with static inner classes in Java), which restricts a class to only contain static methods. C# 3.0 introduces extension methods to allow users to statically add a method to a type (e.g., allowing foo.bar() where bar() can be an imported extension method working on the type of foo).

The Sun Microsystems Java compiler requires that a source file name must match the only public class inside it, while C# allows multiple public classes in the same file, and puts no restrictions on the file name. C# 2.0 and later allows a class definition to be split into several files, by using the partial keyword in the source code. In Java, a public class will always be in its own source file. In C#, source code files and logical units separation are not tightly related.

Exception handling

Java supports checked exceptions (in addition to unchecked exceptions). C# only supports unchecked exceptions. Checked exceptions force the programmer to either declare the exception thrown in a method, or to catch the thrown exception using a try-catch clause.

Checked exceptions can be helpful for good programming practice, ensuring that all errors are dealt with. However Anders Hejlsberg, chief C# language architect, argues that they were to some extent an experiment in Java and that they haven't been shown to be worthwhile except in small example programs.[15][16]

One criticism is that checked exceptions encourage programmers to use an empty catch block (catch (Exception e) {}), which silently eats exceptions, rather than letting the exceptions propagate to a higher-level exception-handling routine. Another criticism of checked exceptions is that a new implementation of a method may cause unanticipated checked exceptions to be thrown, which is a contract-breaking change. This can happen in methods implementing an interface that only declares limited exceptions, or when the underlying implementation of a method changes. To allow for such unanticipated exceptions to be thrown, some programmers simply declare the method can throw any type of exception ("throws Exception"), which defeats the purpose of checked exceptions. In some cases however, exception chaining can be applied instead; re-throwing the exception in a wrapper exception. For example, if an object is changed to access a database instead of a file, an SQLException could be caught and re-thrown as an IOException, since the caller may not need to know the inner workings of the object.

There are also differences between the two languages in treating the try-finally statement. The finally is always executed, even if the try block contains control-passing statements like throw or return. In Java, this may result in unexpected behavior if the try block is left by a return statement with some value, and then the finally block that is executed afterwards is also left by a return statement with a different value. C# resolves this problem by prohibiting any control-passing statements like return or break in the finally block.

A common reason for using try-finally blocks is to guard resource managing code, so that precious resources are guaranteed to be released in the finally block. C# features the using statement as a syntactic shorthand for this common scenario, in which the Dispose() method of the object of the using is always called.

Finally blocks

Java allows flow of control to leave the finally block of a try statement, regardless of the way it was entered. This can cause another control flow statement (such as return) to be terminated mid-execution. For example:

int foo() {
    try {
        return 0;
    } finally {
        return 1;
    }
}

In the above code, the return statement within try block causes control to leave it, and therefore finally block is executed before the actual return happens. However, finally block itself performs a return as well; thus, the original return that caused it to be entered is not actually executed, and the above method returns 1 rather than 0.

In C#, no statements which allow control flow to prematurely leave the finally block are allowed, except for throw. In particular, return is not allowed at all, goto is not allowed if the target label is outside the finally block, and continue and break are not allowed if the nearest enclosing loop is outside the finally block.

Lower level code

The Java Native Interface (JNI) feature allows Java programs to call non-Java code. However, JNI does require the code being called to follow several conventions and impose restrictions on types and names used. This means that an extra adaption layer between legacy code and Java is often needed. This adaption code must be coded in a non-Java language, often C or C++. Java Native Access (JNA) allows easier calling of native code that only requires writing Java code, but comes at a performance cost.

In addition, third party libraries provide for Java-COM bridging, e.g. JACOB (free), and J-Integra for COM (proprietary).

.NET Platform Invoke (P/Invoke) offers the same capability by allowing calls from C# to what Microsoft refers to as unmanaged code. Through metadata attributes the programmer can control exactly how the parameters and results are marshalled, thus avoiding the need for extra adaption code. P/Invoke allows almost complete access to procedural APIs (such as Win32 or POSIX), but limited access to C++ class libraries.

In addition, .NET Framework also provides a .NET-COM bridge, allowing access to COM components as if they were native .NET objects.

C# also allows the programmer to disable the normal type-checking and other safety features of the CLR, which then enables the use of pointer variables. When this feature is used, the programmer must mark the code using the unsafe keyword. JNI, P/Invoke, and "unsafe" code are equally risky features, exposing possible security holes and application instability. An advantage of unsafe, managed code over P/Invoke or JNI is that it allows the programmer to continue to work in the familiar C# environment to accomplish some tasks that otherwise would require calling out to unmanaged code. An assembly (program or library) using unsafe code must be compiled with a special switch and will be marked as such. This enables runtime environments to take special precautions before executing potentially harmful code.

Language history and evolution

Java

Java is older than C# and has built up a large and highly active user base, becoming the lingua franca in many modern branches of computer science, particularly areas which involve networking.[citation needed] Java dominates programming courses at high school and college level in the United States, and there are currently more Java than C# books.[17] Java's maturity and popularity have ensured more third party Java API and libraries (many of them open source)[citation needed] than C#.

An occasionally voiced criticism [18] of the Java language is that it evolves slowly, lacking some features which make fashionable programming patterns and methodologies easier.[citation needed] Some critics argue the designers of C# are perhaps too quick to pander to current trends in programming, thus lacking focus and simplicity.[citation needed] Java's designers seem to have taken a more conservative stand on adding major new features to their language syntax than other current languages, perhaps not wanting to tie the language too tightly with trends which may prove to be dead ends.

These trends have been broken with the Java 5.0 release, which introduced several new major language features: a foreach construct, autoboxing, methods with variable number of parameters (varargs), enumerated types, generic types, and annotations. With the exception of Generics, C# included all these features from its beginning, some under different names.[19] Proposals and specifications for the new features had been worked on in the Java community for considerable time before they were introduced. Indeed, some had been in gestation since before C#'s initial release (e.g., work on Generics formally began in May 1999[20]) such was the Java community's conservatism at that time.

Problem-specific language additions to Java have been considered and, for now at least, rejected. This approach, along with a number of other new languages and technologies that address themselves specifically towards current programming trends, has sparked a renewed debate within the Java camp about the future direction of the Java language and whether its 'conservative evolution' is right.[citation needed]

As of 2008, there is an ongoing debate about the inclusion of closures[21] and properties[22] into the language syntax for Java 7.

C#

By contrast, C# is a relatively new language. Microsoft has studied existing languages such as Java and Object Pascal, and has changed some aspects of the language and runtime environment in response to perceived failures and difficulties with its predecessors. C# accommodates constructs more commonly found in languages such as C++, Delphi (the design of which was Anders Hejlsberg's principal job when he was at Borland), and, in recent C# versions, borrows from dynamic scripting languages such as Ruby and Python.

C# has evolved rapidly, attempting to streamline development for problem-specific features. C# 3.0 adds SQL-like language integrated queries suited for querying data from collections, databases or XML documents, building upon general-purpose language features, including lambda expressions and extension methods, to allow queries to be expressed and optimized for user types.

Before creating C#, Microsoft implemented a modified Java environment, called J++, adding new features in a manner which was in direct contravention to the standards and conventions ensuring the platform neutrality which lies at the heart of Java. This violated the license agreement Microsoft had signed, requiring that standards and specifications be strictly adhered to in return for using the Java name and brand logos. Sun Microsystems sued, and in settling the suit, Microsoft agreed to discontinue J++. (Other existing Microsoft products that used Java were permitted to continue such use for seven years.[23]) With the release of the .NET framework (and C#), the project was revived in the form of J#.

See also

References

  1. ^ [1]
  2. ^ [2]
  3. ^ [3]
  4. ^ [4]
  5. ^ a b "Class BigDecimal". Sun Microsystems. http://java.sun.com/javase/6/docs/api/java/math/BigDecimal.html. Retrieved 2009-12-24. 
  6. ^ "decimal (C# Reference)". Microsoft. http://msdn.microsoft.com/en-us/library/364x0z75%28VS.80%29.aspx. Retrieved 2009-12-24. 
  7. ^ Java Language Specification Third Edition: section 15.9 Class Instance Creation Expressions
  8. ^ Generics in C#, Java, and C++
  9. ^ Richter, Jeffrey (April 2001). "An Introduction to Delegates". MSDN Magazine. http://msdn.microsoft.com/en-ca/magazine/cc301810.aspx. Retrieved 2008-12-23. 
  10. ^ Campbell, Dustin (9 February 2007). "What's In A Closure?". Did it with .NET. http://diditwith.net/PermaLink,guid,235646ae-3476-4893-899d-105e4d48c25b.aspx. Retrieved 2008-12-23. 
  11. ^ Goetz, Brian (26 July 2005). "Java theory and practice: Be a good (event) listener". IBM Developer Works. http://www.ibm.com/developerworks/java/library/j-jtp07265/index.html. Retrieved 2008-12-23. 
  12. ^ a b Java for Scientific Computation: Prospects and Problems
  13. ^ August 1998 Java News
  14. ^ Closures Coming in Java 7
  15. ^ The Trouble with Checked Exceptions
  16. ^ Why doesn't C# have exception specifications?
  17. ^ O'Reilly, Tim (2006-08-02). "Programming Language Trends". Radar. O'Reilly. http://radar.oreilly.com/archives/2006/08/programming_language_trends_1.html. 
  18. ^ i-Technology Viewpoint: Java's Not Evolving Fast Enough
  19. ^ Java 5 catches up with C#
  20. ^ JSR 14: Add Generic Types To The JavaTM Programming Language
  21. ^ Debate over closures for Java
  22. ^ Property Support in Java, the Java Way
  23. ^ CNET. "Sun, Microsoft settle Java suit". http://news.cnet.com/2100-1001-251401.html. 

External links


Advertisements






Got something to say? Make a comment.
Your name
Your email address
Message