Slashdot Mirror


Hejlsberg Talk About Generics in C# and Java

An anonymous reader writes "artima.com has a very interesting interview with Anders Hejlsberg - the Borland guy now at Microsoft who can best be defined as MR C# - doing all the stuff that Borland wouldn't let him do. He discusses generics in C#, Java (1.5) and C++. Naturally there is the chance of bias but he does raise some interesting points againt Java's generics. Specifically that Java's genericised collections will have to box all primitive types as full objects, whereas C# does not. This is a big performance plus for C#. Java created the primitive types in the first place to address performance concerns but appears to be stepping sideways here. I can't help wondering if Sun has taken this approach to get the syntatic sugar in the language without requiring a bytecode change, but perhaps in a future VM version will allow primitive generics (obvioulsy forcing a bytecode regeneration)?"

8 of 128 comments (clear)

  1. Re:Boxing in Java by jovlinger · · Score: 3, Interesting

    Automatic boxing and unboxing will be identical to manual boxing from a performance standpoint.

    I got the impression that C# could actually use generics to instantiate the array at type int, rather than type Integer with autoboxing.

  2. Re:Performance of generics by hibiki_r · · Score: 5, Insightful

    Just read a little further into the article. It seems that to avoid having to make changes in the VM, the Java generics have to become just like the current containers at the bytecode level. The main difference would be taht instead of having to type all the ugly type casts yourself, the compiler would do it for you. Obviously, this doesn't lead to any performance increases over Java 1.4 containters.

    Compare this to, let's say, C++ templates, where the compiler makes a new copy of the template class specifically for each and every type you use on it. That makes the executable size increase a bunch, but it allows the compiler to pay the performance price, making the code perform almost like a program where a human programmer would have written a copy of the template class for each and every type you ever used it with.

    Since the design of the java 1.5 generics is public knowledge, it's pretty easy for anyone with a reasonable programming knowledge to analyze it. It just seems that run-time efficiency wasn't the first thing in the designers minds.

  3. Re:Why Generics? by Aniquel · · Score: 4, Insightful

    A couple different reasons, actually. First, as mentioned in the article, performance. If you're using generics (come on, call them templates!) and compile-time checking, then you don't need to do the dynamic casting at run-time (c# doesn't, according to the article).

    Second, don't scoff at compile-time type checking - I've run into problems on large java projects where there's been some confusion as to what, actually, has been stored in certain collections. Generics prevent this.

    It comes down to this: How much help do you, as a programmer, want?

  4. The other downside to java generics is worse by Matt2000 · · Score: 4, Informative

    I read the article to see what the numbers were on performance differences. Turns out there were none, what a surprise! So as usual, in theory, perhaps maybe there might be a performance difference and maybe it might be significant or not, or both. Until real comparisons are made, safe to ignore.

    What's more important is his other problem with Java generics which is that in runtime it's not possible to tell what type a collection is compiled as, this is to retain bytecode compatibility. So reflection will have no clue on any of this generics stuff, which isn't a deal breaker, it's just a downside I hadn't heard about before.

    --

  5. Re:Why Generics? by Naerbnic · · Score: 4, Insightful
    "To ask the question is to know the answer"

    The easiest response to that, is the point you just brought up. To get some semblance of compile time type checking, you'd have to make your own type. There are various disadvantages to this, among which are:

    • It uses up your precious time to do what should be almost automateable
    • You can't easily fit back your custom class into the standard classes Java would provide. Your derived class, for instance, would be returning class Foo instead of object. Java doesn't allow you to override methods that vary only by return type
    • Depending on naming, the new class may not be apparent to someone using your API to what it is, especially if your custom class is simply a wrapper around a standard class


    As for the benefits of generics, a basic one is that it makes the intent of the code clearer (since you don't want to make a custom type, for the reasons above). The other major one I can come up with right now, is making your interfaces clearer to people who would use your classes. By fully specifying the type (including what is supposed to be in collections), you can make sure the class user is clear on what the interface to a method is, and if he makes a mistake, the compiler will tell him. This means you don't have to deal with all the messy exception handling and such that would go along with just using Object base types.

    I am agreed that the < > syntax can be too verbose at times, especially with something like LongClassName<AnotherName> foo = LongClassName<AnotherName>(). Of course, this leaves us with a quandary, since on the one had we want to be able to easily see and specify types of everything, which would suggest using full typenames everywhere. On the other hand, we could introduce typedef like functionality, but that would have some problems of clarity. It seems that Java has historically, and still is taking the first approach.
    --


    So there I was, juggling apples and small animals, when I accidentally bit into the wrong one...
  6. C# vs Java by astrashe · · Score: 3, Insightful

    I've been reading through the various segments of the interview, and I tend to buy most of what Hejlsberg says on various Java vs. C# issues.

    But I keep coming back to the idea that the changes (or improvements) aren't enough. If you accept that all of the changes are improvements, that they make things better, they're still not enough to justify getting locked into a single vendor, or in learning new libraries.

    C# cleans up some of Java's annoyances, which is great, but the annoyances just aren't big enough to make the shift worthwhile. That's the problem.

    I think the libraries problem is huge for Microsoft. The java libraries are just getting to be so big, complex, and rich that it will be very hard to get people to move away from them.

    I don't think that anyone says there aren't annoying things in Java, parts of it that wouldn't be done differently if the language could be redesigned from scratch. But those annoyances are liveable -- for the most part, you can deal with them.

    Java's has those libraries, though, and one of the reasons the libraries are so rich is that Sun opened up the process to other companies. MS is huge, they have a lot of smart guys, but I just don't think they can compete with Java's comparative openness.

    That's the thing -- you can read about checked exceptions, and agree that it would be nice if java handled things more like C#, but it's not even close to being enough to overcome the value of java's openness vs. Microsoft's closed approach.

    In the end, it really comes down to the business model.

  7. Re:Nothing's changed here... by sab39 · · Score: 4, Informative

    It doesn't have anything to do with autoboxing in Java, but it has everything to do with boxing in Java versus C#.

    Both C# and Java require boxing if you want to put an int into an object variable. They differ in whether that boxing is automatic or not (at least until Java makes it automatic in 1.5), but that's irrelevant: it still happens, so the performance impact is the same in both languages.

    However, if you're trying to put that same int into an ArrayList<int>, the two languages are very different.

    In Java, ArrayList<int> is really just ArrayList<Object> under the covers, and stores its contents into an array of type Object[], so the boxing operation still needs to happen. Hence, there's a performance hit.

    In C#, ArrayList<int> is interpreted as such at the runtime level and the JIT compiler creates native code for it that stores the contents in an array of type int[]. When you store values into that array, no boxing is needed, automatic or otherwise. No performance hit.

    Both C# 1.1 and Java 1.4 collections can hold primitive types if you box them. In Java 1.5, you get some extra syntactic sugar (which C# had from day one) but the boxing still happens. In C# 2.0, generic collections can hold primitive types without boxing. That's the difference that he's trying to get across in this article, and why it's specific to generics.

    All of this is explained very clearly in the article and it amazes me that so many people can't grasp it...

  8. Re:Nothing's changed here... by sab39 · · Score: 3, Informative

    I'm afraid you are wrong.

    While "int" is treated "as if" it were an Object in the CLR, and behaves as if it was a subclass of Object, it really is a value type: It's allocated on the stack, cannot be subclassed, and is passed by value when it's used as a method parameter or return value.

    The same goes for all the other built in primitive types (float, decimal, double, long, short, bool, char etc), along with user-defined Structs and Enums. These are all considered "Value Types" in the CLR.

    When instances of value types need to be treated as Objects, they are boxed, just like in Java, except that it's transparent and automatic and there's no separate class that represents the boxed type - the distinction Java makes between int and Integer simply doesn't exist in C#. (System.Int32 is just an alias for int and isn't equivalent to Integer at all in any way).

    The article clearly states that in Generic C#, the JIT actually creates specialized binary code whenever a generic class is instantiated with a value type argument. It even uses the example of List<int> turning into int[] (remember value types like int can't be subclassed, so the subclass problem doesn't arise).

    C# provides the "illusion" of no primitives, but it's certainly not true that everything's always boxed. It just provides a more elegant and flexible model of boxing than Java does.