In What does this code print? Eric Gunnerson shows this C# code (int derives from object in C#):

using System;

public class A {
    public void F(int i) {
        Console.WriteLine("A: {0}", i);
    }
}

public class B : A {
    public void F(object o) {
        Console.WriteLine("B: {0}", o);
    }
}

public class Test {
    public static void Main() {
        B b = new B();
        b.F(1);
    }
}

And the answer B: 1 surprised me. So I tried the equivalent in Java (three source files)

public class A {
    public void f(Integer i) {
        System.err.println("A: " + i.toString());
    }
}

public class B extends A {
    public void f(Object o) {
        System.err.println("B: " + o.toString());
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.f(new Integer(1));
    }
}

and it printed A: 1. What I expected.

Before I dig deeper into the Java case, let's see why the C# version works the way it does. Eric explains that method dispatch at runtime will occur on the most derived class that holds a method that could satisfy a certain method invocation and then will search for the best match in that class. So here the runtime will find that F in B does match the invocation in Test and is never going to look at A.

The reason for this behavior, he says, is versioning. If you invoke any method on B and some time later anybody introduces a new method into A that would better match your invocation the runtime will still choose B's method.

So how does it work in Java? Sometimes I enjoy digging into the JLS, sick, I know. Java performs much of the method resolution at compile time. At compile time it will determine which method signature matches a certain invocation best - and will select A - and at runtime it will use the method in the most derived class that has the same signature which was determined at compile time.

This has interesting consequences. If you remove the definition of f from A and recompile everything, the the code will (certainly) print B: 1. Now add back f in A and only recompile A but not Test, it still prints B: 1. Only if you recompile Test as well, it will return to A: 1.

In a way Java solves the versioning problem, but only as long as you don't recompile your code against a newer version of A. While C#'s way is counterintuitive (to a seasoned Java developer, at least), it is more predictable at the same time. I'm not sure which way I prefer.

path: /en/dotNet | #

In the past I've been using cc-mode and just told it to use C++ for my C# coding on Linux or my Mac. Not terrific, but it worked.

A post on the Mono developer list pointed to http://mfgames.com/linux/csharp-mode and Dylan Moonfire followed up with a comment that he had just released version 0.4.0. It seems to play well with XEmacs (different other versions I tried all failed for me). Looks like I finally get "internal" highlighted as a keyword.

path: /en/dotNet/XEmacs | #

My "msbuild" search feed today made me discover Waaargh.NET by Stéphane Tombeur that holds some interesting posts. In particular I liked the Creating custom MSBuild tasks and CruiseControl.NET and MSBuild posts.

The first one explains how to write an MSBuild task by converting a NAnt task - which turns out to be mostly a matter of six simple steps. I assume that it would get more complex for more elaborated tasks, but this really looks rather straight forward.

The second one comes with an MSBuilder based on NAntBuilder that can be used to drop into CruiseControl.NET and you are done. Nice work, I hope it finds its way into cc.net.

path: /en/dotNet/msbuild | #

Mitch Denny has a little history lesson on MSBuild (via Jomo Fisher).

I certainly have to disagree with

Over the years, as Ant got more popular the beautiful target/depedency model got poluted by stinking proceduralists
I doubt that MSBuild is less procedural than a proper Ant build file, but that's just me.

The very idea of items in MSBuild - tasks, targets and even projects declaring their inputs and outputs, which would allow pipes of tasks or projects to depend of the outputs of other projects - still has a lot of appeal to me.

path: /en/dotNet/msbuild | #

Have I ever said that IKVM.NET is cool? I should.

Octavo:/tmp bodewig$ cat > build.xml
<project>
  <echo>os.name = ${os.name}</echo>
  <echo>java.home = ${java.home}</echo>
  <echo>ant.java.version = ${ant.java.version}</echo>
  <echo>java.vendor = ${java.vendor}</echo>
  <echo>java.version = ${java.version}</echo>
</project>
^D
Octavo:/tmp bodewig$ ant
Buildfile: build.xml
     [echo] os.name = Mac OS X
     [echo] java.home = /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home
     [echo] ant.java.version = 1.4
     [echo] java.vendor = Apple Computer, Inc.
     [echo] java.version = 1.4.2_05

BUILD SUCCESSFUL
Total time: 2 seconds


Octavo:/tmp bodewig$ JAVACMD=/usr/bin/mono ANT_OPTS=/Users/bodewig/ikvm/bin/ikvm.exe ant
Unable to locate tools.jar. Expected to find it in /Users/bodewig/ikvm/bin/lib/tools.jar
Buildfile: build.xml
     [echo] os.name = Unix 7.8.0.0
     [echo] java.home = /Users/bodewig/ikvm/bin
     [echo] ant.java.version = 1.5
     [echo] java.vendor = Jeroen Frijters
     [echo] java.version = 1.4

BUILD SUCCESSFUL
Total time: 23 seconds

More experiments to come.

The difference between in java.version and ant.java.version means, GNU CLASSPATH already has java.lang.Readable

path: /en/dotNet/ikvmnet | #