When I speak to my Tamil friends in English, I don’t really speak English, it’s Tanglish (Tamil + English)! For example, “Yes?” (the tone of which implies, “Is it so?”) and “No?” (by which I mean, “Is it not?”), become “Yes..aa” and “No..aa”! In Tamil, questions are formed by adding an ‘a’ suffix to words, so Tamilians find it convenient to form questions in English by adding the same suffix to English words!
To someone who doesn’t understand Tamil, it’s very amusing! As we can see, there are many pitfalls when you think in one language, and speak in another. Similarly, when you have considerable experience programming in one language, and start programming in another new language, there are numerous pitfalls associated with that transition.
Languages like C++, Java and C# are closely related, because they inherit a lot from C. The code segments that have similar syntax can have subtly different semantics, and transitioning between these languages can cause bugs.
A very good example is the ~
symbol used for destructors in C++ and C#: the syntax and name of the feature (destructor) is the same, but there is a subtle difference. In C++, destructors are deterministic (the destructor is called immediately after the object’s use is over), whereas in C#, destructors are non-deterministic (they are called by the Garbage Collector, and need not be called immediately after the use of the object is over). C++ programmers who’re new to C# can introduce bugs if they assume the deterministic behaviour of destructors while coding in C#.
Another example is the C++ virtual keyword. In C++, using the virtual keyword in the base method makes it a virtual method, and the overriding method need not use the virtual keyword; however, using the virtual keyword in the overriding method is recommended as a best practice, since it improves the readability of the code. However, if seasoned C++ programmers start programming in C#, and follow this C++ best practice in C#, they will introduce a subtle bug: in C#, if you use the virtual keyword in the overriding method, it becomes “hiding”, and not overriding!
So let’s look at some actual code segments illustrating such language transition bugs. Specifically, we’ll focus on Java and C# differences. Here is our first code segment:
int foo() { return true ? null : 0; }
Well, your first question is sure to be, “Does it really compile?” The answer is: “It depends!” In C#, you’ll get a compiler error for attempting to convert a null
to an int
. But you’ll be really surprised that in Java, it compiles, but fails with a NullPointerException
during execution. The code compiles in Java because of some arcane language rules on boxing and unboxing.
Now, how about the following code?
int i = 10; int j = 10; return ((Object)i == (Object)j);
If you’re a Java programmer, you would say the code returns true; if you’re a C# programmer, you would say false! In C#, boxing a primitive type to a reference type causes the creation of two different reference-type objects, and hence the condition check will return false. In Java, boxing a primitive type to a reference type reuses the existing boxed object, and hence, it’s true!
Here is our last example:
byte b1 = 127; byte b2 = 1; byte b3 = (byte)(b1 + b2);
Now, what is the value of b3
? It’s 128 for a C# programmer and -128 for a Java programmer! In C#, a byte is unsigned, so the range is from 0 to 255; in Java, a byte is signed, so the range is from -128 to +127!
If you’ve been bitten by such bugs, drop me an email; I’ll be glad to hear from you. And here’s something very important: Allow me to wish you a happy New Year!
kya baat hai Linux Bhai..maja aa gya..aur sunao Holi kaisi rahi..
kya baat hai Linux Bhai..maja aa gya..aur sunao Holi kaisi rahi..