4 ms·
What exactly is missing, or better in C#? I'm surprised because I've been programming in OCaml for a long time, and never missed "real" (i.e. non-erased) generi
by tomp 10y ago
What exactly is missing, or better in C#? I'm surprised because I've been programming in OCaml for a long time, and never missed "real" (i.e. non-erased) generics.
- adevine 10y agoFor me, it's mainly that you know the runtime type of the type parameter, so you can do things like new T() in your generic class.
- kmiroslav 10y agoPass a factory `createT()` instead, problem solved.
- adevine 10y agoExactly - except it's gross and results in a lot of annoying boilerplate code for what should be considered a simple operation. Tons of generic APIs essentially do the same thing by passing in the class object in the constructor, e.g. http://stackoverflow.com/a/1090488/1075909 http://stackoverflow.com/a/1090488/1075909 . The question for people not that familiar with the Java type system is often "Why do I have to pass in the class object when I just declared the type parameter in my instance?" That's not the only thing you need to workaround because of type erasure (the "TypeToken" stuff in a lot of deserialization libraries is another one that comes to mind frequently), but it's probably the first annoying example people hit.
- kmiroslav 10y agoErasure is not the problem here, you need to be able to specify a type constraint that will allow you to invoke T(). What if T is an interface? An abstract class? A class with no default constructor? The only reasonable way to do this is to accept a lambda that tells the compiler exactly what call is legal to create an instance of T. And that's called a factory.
- adevine 10y agoYes, good point. But if you did have a type constraint, like C#, you would still need the runtime type info to know what to create. This is legal in C#: public static T Factory<T>() where T:new() { return new T(); }
- barrkel 10y agoUnboxed values; this primarily affects performance, particularly memory performance, but with a sufficiently smart compiler could be worked around. It's unlikely any very clever JVM optimizations would see wins here though, as the assumption that everything is boxed is idiomatic. Having a type argument available; as adevine mentions, performing type-level things rather than just instance-level things. A smarter language than Java could handle this with hidden arguments, or passing along a dispatch table for type-specific actions when constructing a generic type. Things get trickier when you're e.g. storing a reference to a static generic method. In reality, there's a continuum between C++-style generics-as-parameterized-syntax-trees and Java's generics-as-ignorable-type-checker-façade. Going full C++ isn't what you want; the error messages on failure to instantiate are unpleasant. Going full Java leaves you with a few holes. C# is probably a small bit too far in the C++ direction - instantiations can add up, despite .NET reusing instantiations where the type arguments are object references (that is, the CLR will effectively erase types if your type arguments are reference types, but you can't observe this without escaping the type system).