InfoQ

News

A Comparison of C# to Java, Updated

Posted by Hartmut Wilms on May 02, 2007 06:25 AM

Community
.NET,
Java
Topics
Programming
Tags
Java SE ,
C#

In 2001 Dare Obasanjo has written one of the most comprehensive and accurate "Comparison of Microsoft's C# Programming Language to Sun Microsystems' Java Programming Language". Now he has updated his comparison in order to reflect the changes in the current versions of both languages: Microsoft C# 2.0 and Java Standard Edition 6.

Dare Obasanjo's article is an objective comparison of the features and concepts of C# and Java. What distinguishes his work from others is that he gives a complete overview of the languages and their implementations on both platforms. Thereby his comparison also serves as a language reference and an explanation of the feature implementations as well as their pros and cons. 

The article is structured as follows:

  1. What features are the same in C# and Java?
  2. What features exist in both languages, but differ in minor manner?
  3. What concepts exist in both languages, but differ significantly?
  4. What features or concepts exist in C#, which have no counterpart in Java?
  5. What features or concepts exist in Java, which have no counterpart in C#?
  6. Conclusion

The comparison of Generics and Metadata Annotations are especially interesting, because they show and explain the apparently minor differences in the Java and C# implementation, which have some unobvious consequences when using these features in real-world projects. Another interesting aspect of the article is that Dare Obasonjo has included his conclusion from 2001 in the current version, showing the changing directions of language evolution in Java and C#:

[...] 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 different 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 differences 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.

Dare Obasanjo's comparison offers a lot of information for developers who switch from Java to C# or vice versa as well as developers who want to get some additional information about the features and concepts of their language.

11 comments

Watch Thread Reply

Erratum by Marko Topolnik Posted May 2, 2007 10:33 AM
Erratum (con'td) by Stefan Wenig Posted May 3, 2007 3:26 AM
Re: Erratum (con'td) by David Skelly Posted May 3, 2007 7:44 AM
Re: Erratum (con'td) by Stefan Wenig Posted May 3, 2007 10:03 AM
Re: Erratum (con'td) by Marko Topolnik Posted May 5, 2007 11:20 AM
Re: Erratum (con'td) by Stefan Wenig Posted May 5, 2007 11:43 AM
Re: Erratum (con'td) by Marko Topolnik Posted May 7, 2007 6:46 AM
Re: Erratum (con'td) by Stefan Wenig Posted May 7, 2007 8:32 AM
Re: Erratum (con'td) by Marko Topolnik Posted May 7, 2007 10:14 AM
Re: Erratum (con'td) by Marko Topolnik Posted May 8, 2007 1:52 AM
Re: Erratum (con'td) by Stefan Wenig Posted May 8, 2007 6:13 AM
  1. Back to top

    Erratum

    May 2, 2007 10:33 AM by Marko Topolnik

    I was quite astonished to find that Dare managed to get confused about access modifiers in Java. In B.7. he mentions the C++ fans who were disappointed to see the semantics of protected changed in Java -- which is actually true but not in the way he describes it: "protected" in Java gives the access rights as in C++, but in union with the package-private access rigths. However, he describes "protected" as if he was describing "package-private" and does not mention "package-private" at all.

  2. Back to top

    Erratum (con'td)

    May 3, 2007 3:26 AM by Stefan Wenig

    this article sure is an interesting read, dare did compile a lot of information. that's really great if you know one language well and want to learn the other - the sublte differences are hard to find out in any other way. however, he got many details wrong. i just browsed over the article and found quite a lot of mistakes: final in java is the same as readonly in c#: values cannot be modified after initialization. however, they are stored as values. const in c# is a compile-time constant, meaning that references to consts are replaced by their literal value at compile time, and not stored anywhere at runtime. on generics: "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." this is not quite the same as the correct description: JIT-generated code is shared for all reference types. static type checking is still very specific about type arguments. "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." they are of course typesafe. "A Java inner class can be considered as a one-to-one relationship between the inner class and its enclosing class where for each instance of the enclosing class there exists a corresponding instance of the inner class that has access to the enclosing class's instance variables and contains no static methods." as far as my little java knowledge takes me, inner classes still have to be new'd up, they only keep an implicit reference to their owner (a "parent" field you'd have to initialize via the constructor otherwise, much like the this parameter). so there can be zero or more instances of inner classes for each outer-class object, not quite a 1:1 relationship... the "double checked locking is broken" declaration is outdated. afaik, the current java version makes volatile work in this scenario. on the other hand, the volatile keyword is no more strictly necessary in the .net 2.0 memory model. "Secondly one needs to define 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 [...] or has covariant return types and contravariant parameter types [...] can be created and used [...]." covariant return types are supported by the c# language, but contravariant parameter types are not. the latter are however supported by the CLR, so a call to CreateDelegate will provide both co- and contravariance. "(In fact, C#'s built-in types such as int are actually implemented as structs in the runtime library)." this could lead one to think that using an int in c# leads to the creation of a System.Int32 object through standard instantiation mechanisms. however, basic types like int are of course hard coded into the CLR and not treated like user-defined value types. "NOTE: The as operator cannot be used to convert to or from value types." it can, using nullable value types: object o = null; int? i = o as int?; "x ?? y is equivalent to x == (null ? y : x). " ouch! ;-) the connection between anonymous classes in java and anonymous methods in c# is completely missing, as is the concept of closures. the conclusion fails to mention how c# is becoming more functional in version 3.0. lambda expressions and conversion of expressions to data (abstract syntax trees) are exciting features far beyond the scope of data-oriented LINQ. toghether with new features like extension methods, c#'s anonymous types (completely unlike java's) and type inference this can change the way you program quite radically. the value of continuations is quite underestimated too, they can be used for so much more interesting things that just building iterators for collection classes. Still worth reading, I just hope those mistakes (and there are probably some i didn't spot) are corrected soon.

  3. Back to top

    Re: Erratum (con'td)

    May 3, 2007 7:44 AM by David Skelly

    final in java is the same as readonly in c#: values cannot be modified after initialization. however, they are stored as values. const in c# is a compile-time constant, meaning that references to consts are replaced by their literal value at compile time, and not stored anywhere at runtime.
    You are correct about variables or parameters declared final in Java. However, just to confuse things static final variables in Java are compiled as in-line constants. In other words, if you change a static final value, you need to recompile everything that uses it or they will continue using the old value. That catches out every Java newbie sooner or later. So, although I don't know C#, it sounds to me as if final is the same as readonly and static final is the same as const. Is that right?
    as far as my little java knowledge takes me, inner classes still have to be new'd up, they only keep an implicit reference to their owner (a "parent" field you'd have to initialize via the constructor otherwise, much like the this parameter). so there can be zero or more instances of inner classes for each outer-class object, not quite a 1:1 relationship
    Correct. Also, although inner classes cannot contain static methods of their own, they can access static methods of the containing outer class.

  4. Back to top

    Re: Erratum (con'td)

    May 3, 2007 10:03 AM by Stefan Wenig

    That catches out every Java newbie sooner or later. So, although I don't know C#, it sounds to me as if final is the same as readonly and static final is the same as const. Is that right?
    you're right: it'd have caught me, and what you describe is exactly how const works in c#. however, from the java specs i gather that a final field is treated as a constant if it is assigned a fixed literal of a basic data type. is the following correct? class C { final String s1 = "this is a compile-time constant"; static final MyString s2 = new MyString ("this is stored in a field"); static final string s2; C (string suffix) { s2 = "this is stored in a field" + suffix; } } it's just usually the other way 'round. in c# it's simple: if the value is not of a primitive type or has to be calculated at runtime, using "const" does not compile. so readonly and const always work as expected.

  5. Back to top

    Re: Erratum (con'td)

    May 5, 2007 11:20 AM by Marko Topolnik

    Is the following correct?
    class C {
      final String s1 = 
        "this is a compile-time constant";
      static final MyString s2 = 
        new MyString ("this is stored in a field");
      static final string s2;
      C (string suffix) {
        s2 = "this is stored in a field" + suffix; 
      }
    }
    Actually, in Java it IS the other way 'round: only references to a static final field can be replaced by their value calculated at compile time. A final field is an instance field and a reference to it is always left as a reference. So, your example should be corrected as follows:
    class C {
      final String s1 = 
        "this is a stored in an instance field";
      static final String s1a = 
        "this is a compile-time constant";
      static final MyString s2 = 
        new MyString ("this is stored in a field");
      static final string s2;
      C (string suffix) {
        s2 = "this is stored in a field" + suffix; 
      }
    }

  6. Back to top

    Re: Erratum (con'td)

    May 5, 2007 11:43 AM by Stefan Wenig

    That's exactly what David was saying. I'm by no means a Java expert, but the only reference to final fields being treated as compiled time constants in the Java specs is §4.12.4, and it seems to contradict your statements. http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#10931 "We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28) a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9) and definite assignment (§16)."

  7. Back to top

    Re: Erratum (con'td)

    May 7, 2007 6:46 AM by Marko Topolnik

    (I am not sure which of my statements is being disputed, so I assume that it is the claim that only a reference to a static final field can be replaced by its compile-time value.) The question is not whether something is a constant variable, but whether a REFERENCE to it is replaced by its compile-time value or it is left as a reference to a field. A reference to a a final instance variable will always be compiled as such: the only way to refer to it is via a reference to the containing instance and in order to obtain such a reference there will always be a constructor involved, making the whole expression of referencing the final field a non-constant expression.

  8. Back to top

    Re: Erratum (con'td)

    May 7, 2007 8:32 AM by Stefan Wenig

    Sure, I understand so much already, and it would make perfect sense too. I'm just wondering why the specs won't say so. Maybe that's a difference between the reference implemenation and the written specs, or I didn't read the specs carefully enough. Anyway, thanks again for clearing this up.

  9. Back to top

    Re: Erratum (con'td)

    May 7, 2007 10:14 AM by Marko Topolnik

    As is typical of the JLS, it does specify everything and leaves almost anything open to interpretation, but much of the facts are either difficult to find or are burried deep into the implications of several disparate sections taken together. But, in this particular case you could have gotten to precisely the info you need if you followed one of the links in the passage you cited above: §13.4.9. Again, of all the links it is far from obvious which one will tell you what you need :)

  10. Back to top

    Re: Erratum (con'td)

    May 8, 2007 1:52 AM by Marko Topolnik

    ...and leaves almost anything open to interpretation...
    I meant "almost nothing", of course :) And when rereading that section I realized that once again it is not clear from it what happens to final instance fields because it only talks about static final fields. Of course, a spec does not have the need to spell out any falsity that we mere humans are likely to assume, it only deals with how the things are.

  11. Back to top

    Re: Erratum (con'td)

    May 8, 2007 6:13 AM by Stefan Wenig

    I think this looks rather like a mistake. While the samples in the section use only static final fields, describing the semantics of final fields and not explicitly noting that the whole section only applies to those that are static makes little sense.

Educational Content

Bindings, Platforms, and Innovation

This presentation focuses on the Internet and separating myth from fact, history from the future, and the mundane from the imaginative. Bob Frankston presents a vision of what could and should be.

Orchestrating Long Running Activities with JBoss / JBPM

This article explores the use of JBoss and jBPM to implement design solutions that effectively address the issue of orchestrating long running activities.

Neo4j - The Benefits of Graph Databases

This presentation covers the use of graph databases as an optimal solution for data that is difficult to fit in static tables, rapidly evolving data or data that has a lot of optional attributes.

Realistic about Risk: Software development with Real Options

This session introduces Real Options and shows how it can help in running your project. Real Options is a decision-making process that can be used to manage risk.

Communication Flexibility Using Bindings

This article discusses the use of bindings on services and references (including the instance of non-configured bindings) as the means to implement SCA communications in a Web and SOA environment.

Writing DSLs in Groovy

After a short introduction to DSLs, Scott Davis plays with the keyboard showing how to approach the creation of a DSL by typing working snippets of Groovy code that get executed.

Scaling Agile with C/ALM (Collaborative Application Lifecycle Management)

IBM Rational and InfoQ present, Scaling Agile with C/ALM, an eBook showing organizations how to become “finely tuned software delivery machines” by enabling team integration and scaling.

Concurrent Programming with Microsoft F#

Amanda Laucher presents a real life enterprise application written in F#. She shows actual code snippets, explaining design decisions and suggesting how to use some of the F# constructs.