I have a question to which I have not found an answer.
Let’s say we have in either java or c# the following code:
class Car {
/* car stuff */
}
And then in Java
class Truck extends Car {
/* truck stuff */
}
and C#
class Truck : Car {
/* truck stuff again */
}
In C# the following works just fine:
List<Car> carList = new List<Car>();
//add some objects to the collection
foreach(Truck t in carList)
//do stuff with only the Truck objects in the carList collection
This works because Truck is a subclass of Car which in simple terms means that each Truck is also a Car. The thing is though, that type checking is done and only Trucks are selected from carList.
If we try the same thing in Java:
List<Car> carList = new ArrayList<Car>();
//add some objects to the collection
for(Truck t : carList)
//**PROBLEM**
Because of the code inside the enhanced loop, the code will not even compile. Instead we have to do something like this to get the same effect:
for(Car t : carList)
if(t instanceof Car)
//cast t to Truck and do truck stuff with it
It is the same idea which in C# works without any problem, but in Java you need extra code. Even the syntax is almost the same!
Is there a reason why it does not work in Java?
Nope, it’s not. If your list contains anything but
Trucks, a runtime exception will occur in C#. Basically, in C#, the followingbehaves like
The Java variant, on the other hand, is type-safe: You have to make the cast and the type-checking yourself.
So, why do Java and C# behave differently? This is my guess:
C# had the
foreachkeyword before it had generics. Thus, there was no possibility to have aList<Car>. If C# had opted for the Java way offoreach, you’d have to writewhich is annoying. On the other hand, the extended for loop and generics were introduced in Java in the same version (Java 5), so there was no need for automatic casts.