25 ms·
How generics were added to .NET
- zastrowm 9y agoThis surprised me: > It was only through the total dedication of Microsoft Research, Cambridge during 1998-2004, to doing a complete, high quality implementation in both the CLR (including NGEN, debugging, JIT, AppDomains, concurrent loading and many other aspects), and the C# compiler, that the project proceeded. I didn't realize that it was less a "must-have" and more of a "research and if-possible" task. I wonder how the .NET framework/languages would have changed if they went with type erasure. Would we even still talking about .NET today?
- nikanj 9y agoWe're still talking about Java, which does type erasure. Oracle has really been phoning it in for many years, and despite that the platform is still going strong. Killing large, entrenched platforms is not easy. Windows remains 800lb gorilla on the desktop, and C# is Microsoft's recommended environment on it. It's hardly surprising that .NET remains relevant.
- nathanaldensr 9y agoI've been working with .NET since it was in beta in 2001, and I've never considered .NET's strength to be its desktop story. .NET (and now .NET Core) are awesome because of C# and the BCL's generally excellent design. .NET is an excellent choice for building server-side applications of all kinds. .NET Core removed that last complaint I had about .NET: it wasn't cross-platform. It's a great time to be a .NET developer.
- zamalek 9y ago.Net is also well designed. Some of the most subtle design choices drastically exaggerate poor choices in other languages - one example that has always stuck with me is how well C# namespaces are designed. Not only because they are frictionless, but also because of the lack of global namespace types in the standard library. It's a tiny detail, but .Net is just that: hundreds of well-executed small details.
- guelo 9y agoI disagree with you about namespaces. I find Java's packages more useful since they give you access control which increases encapsulation. If I want a factory method guarding the instantiation of a class in java I can make the factory public and the class package private. In C# the only answer for this type of encapsulation are assemblies but they're much heavier weight and it is recommended not to have too many of them in a project.
- BitterAmethyst 9y agoYou can make the constructors on the class private and have a public static method on the class that does the instantiation.
- guelo 9y agoFor the simple case yes. But if you want several classes cooperating, maybe helpers or related data classes, your options are assemblies or like you said to shove everything into one giant class. You have less flexibility of separating things out.
- eldavido 9y agoI think the only way you get this is having someone very, very experienced leading the project. MS had Anders Hejlsberg, who hasn't done much in life, except leading the Turbo Pascal and Delphi efforts, two of the most successful rapid app design languages of the 90s (note: heavy sarcasm in last sentence) I'm not one bit surprised this is the the guy leading the C# effort's second or third language.
- cm2187 9y agoOn large platforms, I am going to piss off people but I'll do it anyway. It's not because a language is widely used that it is a well designed language. Javascript, VBA and php immediatly come to my mind. There are many other reasons for a language to be a heavy weight other than its own merit.
- candiodari 9y agoThere are many metrics to judge a programming language by, and even different "axes". Going from theoretical correctness, consistency, type system soundness all the way to ease of development, "batteries included", empowerment, developer productivity (on small and very large programs, as that is not the same), and more recently "forcing" good practices. Even popularity is a value, as it automatically provides a community, but it's also a pitfall, as massive popularity inevitably means the average programmer of language X becomes as smart, careful and reliable as the average programmer irrespective of language. And, to put it mildly, that's not a positive evolution. That, above all others, was VB and Delphi's downfall. On three axes, I would argue VB, Javascript and Delphi did/do incredibly well: ease of development (of small-ish programs), and the deployment story, as well as the empowerment they provided. On things like consistency, developer productivity, batteries included (Delphi was better on the batteries included front), type system soundness, ... they were somewhat sub-par. It's just what people value at the time. And of course, it is critical during a career in development to distinguish yourself from the average programmer.
- eldavido 9y agoThis reminds me of Peter Lynch's comment about the stock market: "a voting machine in the short term, but a weighing machine in the long term". In the short-term, languages with good developer outreach and other factors win. But you don't get things like generics or the .NET TPL without some serious long-term vision. I really do believe well-designed languages win over a long enough timescale.
- zastrowm 9y agoYeah, but I wonder if .NET wouldn't have succeeded until .NET Core without generics as a distinguishing feature. I feel like generics + some of the features built on them (LINQ+TPL+etc.) is what let .NET/C# stand apart from Java. I'm not necessarily saying it would have failed, but I do wonder :: )
- tatersolid 9y agoC# succeeded based on the strength of Visual Studio. Sure, the language being nicely designed and having some code translation tools helped people switch from VB. But C# being the “best supported” language in Visual Studio. The productivity gains for developers were too real to ignore, managers saw it, and bought into the Visual Studio ecosystem en masse.
- ragebol 9y agoIn turn, Visual Studio has great support for C# because of the C#'s great type system.
- forinti 9y agoDid they really have to split the library into generic/non generic? I think Java handled that much better. It's been more than a decade since I last used C#, so excuse me if I recall incorrectly.
- nathanaldensr 9y agoI'm not sure what you mean by "split the library," but what Microsoft did do is introduce generic versions of many popular and essential classes. For example, the untyped ArrayList became Collection<T>, List<T>, etc. Microsoft did this to retain backward compatibility with existing code.
- enitihas 9y agoJava didn't handle it much better, they simply chose a different tradeoff. They chose to implement generics via type erasure, which basically means List<String> and List are the exact same classes at runtime. .NET chose to implement specialised generics. Many people think that is a better tradeoff.
- KMag 9y agoNote that Java's originally only generic type, the array, has C#-style reified generics. The early JVM implementors should have felt a bit dirty in providing reified generics support for arrays at the VM-level without at least having a forward-compatible VM-level provision for general reified generics.
- Someone 9y agoI think they made the right choice at the time. Targeting devices smaller than desktop computers about 5 years before C# (in a time when Moore’s law was in full swing), they had to cram the jvm in much smaller systems than C# targeted.
- int_19h 9y agoC# did the same exact trade-off in 1.0.
- krat0sprakhar 9y ago> Ultimately, an erasure model of generics would have been adopted, as for Java, since the CLR team would never have pursued a in-the-VM generics design without external help. Can someone explain why "in-the-VM" generics design is better than the erasure model of Java?
- rusbus 9y agoIn Java, you can't make runtime decisions based on the generic type of an object. Eg. you can't have a List<?> and check to see if it's a List<Foo> or a List<Bar> -- that information has been erased. You could look at the head of the list to make that determination, (because the List members still have a concrete type), but that isn't a general purpose solution. Languages like Scala use manifests to preserve the information but it's a major kludge.
- yarg 9y agoLooking at the head of a List does not work. The class of that element is within the scope of <? extends ListType>, an is not necessarily not ListType.
- rusanu 9y agoNot to mention that an empty list still has a type...
- yarg 9y ago*and is not necessarily ListType. Idiot.
- Twisol 9y agoFor the downvoters, the author is correcting themselves after the edit window. It's clearly self-deprecating humor, not a personal attack.
- Groxx 9y agoTo spell this out so it's a bit more obvious, given a Thing at head of a list, you could have: - a List<Thing> - a List<ThingSuperclass> - a List<? extends Thing> - a List<? super ThingSubclass> - a List<IThing> - a List<ILiterallyAnyImplementedIFace> - a List<IHaventForgottenInterfacesCanExtendOthers> - a List<Object> - a List<I'm probably forgetting some possibilities> And you have no way of knowing which it is. So yes, it's a boundary, which is significantly more than nothing. But far less useful than it feels like at first.
- ChicagoDave 9y agoI started looking at the source diffs and it triggers a panic attack. That's a ton of work. All the more reason to admire and appreciate MS Research and the development of C# generics. Really amazing accomplishment. And Linq is one of the single greatest inventions in modern day programming.
- btschaegg 9y agoRegarding LINQ: I really like certain parts of it, dislike others (mainly inline Select-statements and the EntityFramework built on top of it), but I'd be hard-pressed to call it the greatest invention of any time. PEP 255 laid the ground work for similar language features in 2001, and I doubt that the python guys "invented" all of that out of thin air (cf. Reference #4 in the PEP). What you can argue is that LINQ made this stuff available to more developers (with useful syntax and in a statically typed language, which also must have taken a lot of work), but filter/map/reduce have been around for quite a while. That obviously doesn't make it less useful or the underlying tech less impressive though.
- coldtea 9y ago>PEP 255 laid the ground work for similar language features in 2001, and I doubt that the python guys "invented" all of that out of thin air (cf. Reference #4 in the PEP). LINQ is not about generators...
- btschaegg 9y agoThe IEnumerable parts are mainly enabled by coroutines, which for this case more or less equate to generators. The other parts are pretty much what I've already seen so much problems with that I wouldn't touch them with a 10 foot pole (see the "black magic" comment by others, that sums it up nicely for me). But those are also more or less just about building ASTs and transforming them, something Lisp has done for decades.
- tehlike 9y agoThe magic behind LINQ is that it's a query layer on top of a backing data store. When it first came out, you'd see data providers written against twitter, file system and everything like that. Then entity framework & nhibernate linq provider came out. It was great, hid a lot of details from user, brought static type checking to otherwise very hard to "verify" sql. You'd now think in terms of objects, and not tables. Linq compiler compiled the whole query into a AST, which you could then convert to a backing query your data store could understand. To date, I still think Linq was great. I was indifferent to the "sqlized linq", but i liked the lambda quite a lot. It was a nice abstraction and a pretty good language to write queries on. Disclaimer: I worked on NHibernate Linq integration ~10 years ago.
- msie 9y agoIf it took 6 years to get generics into .NET, we can't fault the Golang guys for taking their time too.
- tehlike 9y agogolang generics is templates, or is it not?
- masklinn 9y agoGolang doesn't have user-defined generics (parametric polymorphism).
- josteink 9y agoIt took them 6 years to do it properly on top of an existing framework with the aim to maintain a crazy level of compatibility. They did so because they knew the advantages to be massive. And so does everyone else at this point. That golang decided to forego that wisdom when they started from scratch (and thus create a complex compatibility-story if they were to add it later) is entirely their own fault.
- msie 9y agoSo the Golang guys are in the same situation now, aren't they? Isn't it a bit unfair to fault them for not including generics from the beginning?
- josteink 9y ago> Isn't it a bit unfair to fault them for not including generics from the beginning? No. Because that would be much easier and was the only obvious answer. They took a shortcut, hoped nobody noticed and later when people started complaining about this obvious omission in a modern language, tried to weasel their way out of with some “complexity” bullshit and how “people wouldn’t understand”. So I can fault them for both not including it and then later being disenginious about why. For this glaring omission the golang designers deserve nothing but ridicule.
- enricosada 9y agoIs already at the beginning of the article, but should be more visibible how MS Research and Don Syme seen the opportunity to add generics (neeeded for F#) and added that. With design already supporting later addition like variance. Not just the design, the real implementation too in the existing already complex CLR codebase. And that include lot of areas like NGEN, AppDomains, etc, so is no small feat at all, for a production ready framework already used by lot of developers. I am programming in .NET Framework from v1.0, the v2.0 (with generics) was a clear cut, so is not something you can add too late because it become pervasive in the framework who leverage it in the design (generics in v2.0, LINQ in v3.0, TPL and Async v4.0) As a note, .NET continue to support non generic collections for backward compatibility, but usage is deprecated. Really interesting piece of .NET history in https://blogs.msdn.microsoft.com/dsyme/2011/03/15/netc-generics-history-some-photos-from-feb-1999/ https://blogs.msdn.microsoft.com/dsyme/2011/03/15/netc-gener...
- matthewwarren 9y ago> Is already at the beginning of the article, but should be more visibible how MS Research and Don Syme seen the opportunity to add generics (neeeded for F#) and added that. With design already supporting later addition like variance. I definitely agree, that's why I put it right at the start of the post :-)
- candiodari 9y agoDoes anybody remember the article about their generics implementation in assembly ? How they basically were able to reduce the cost of generics by observing they needed only 3 implementations, by writing specialized versions, one for 8-64 bit values (just one version), and then one for 64 bit pointers, and one for structs (struct passed in by having length and value).
- matthewwarren 9y ago> Does anybody remember the article about their generics implementation in assembly ? Do you mean http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/ http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-t... or https://blogs.msdn.microsoft.com/joelpob/2004/11/17/clr-generics-and-code-sharing/ https://blogs.msdn.microsoft.com/joelpob/2004/11/17/clr-gene... They're 2 articles I came across that covered the low-level details of the generic impl.