I am a boxing fan. I enjoy ESPN Friday Night Fights not so much because of type of match-ups they make (they really are making bad ones lately), but in large part because of Teddy’s Atlas commentary. Teddy Atlas is good, old school, some would say dinosaur, boxing trainer. With Teddy they say, you get what you see, he is not pretending to be something he is not, love it or hate it. Good or bad.
One of the things he often talks about during fights is the need for a fighter to know his identify. Whether they are inside or outside fighter. Whether they use their natural given resources in most effective way, whether they work with them, or against them. Not knowing your identity makes you much less effective. If you have long hands you should be outside fighter, you need room to throw punches and you are much less effective inside in close range.
I believe that same applies to programming languages. They are “born” with certain identities. Once they start losing that identity they start slow and certain death. Soon they will be replaced with something that has clearly defined identity.
This is what is happening right now with C#. It is losing its identity. C# was created as strongly typed language and that is its core identity. Now, some big brains in Microsoft, with apparently nothing to do, are adding dynamic typing to C#. Why? I don’t know why, they probably have lot of very good sounding explanations for it, but what this actually marks is beginning of the end of C# as language. It will be replaced in couple of years, I can’t say whether it is 4 or 10, but it will be replaced with language that has its identity clearly defined. Not replaced in sense that we’ll just throw it away, languages don’t die like that, but replaced in sense that new development will move to something else. VB 5/6 was replaced that way with .NET and C#.
C# will get diluted with so much unnecessary language features that nobody will want or like to use it effectively. I don’t think we need all this LINQ, Lambda, var typing and least of all dynamic keyword… It’s just junk that gets added… How about some decent Data Access Layer? Or fixing font, line and image rendering in WPF? Or fixing VS.NET WPF designer? Or wrapping up IronRuby? Nah, adding dynamic, LINQ and var typing to C# is much more fun.
I already start seeing people using var and dynamic for everything. Every single thing. And they’ll force you to use it too, since they will develop frameworks that rely on these features so you must use them as well. Then, when things start blowing up, because dynamic typing is not really dynamic, but a compiler gimmick, people will start throwing language away. We’ll hear it is not readable anymore, or it is too complex to learn, or… You name it…
Now, I don’t have anything against dynamic languages at all. I am not that grumpy old troll that can’t learn something new. That’s not it. I use Ruby and like it. JavaScript is fine too, thank you very much. But, when you need dynamic language then use dynamic language not one that is kind of dynamic.
It is this loss of identity that is bothering me. C# is simply not created as dynamically typed language and adding dynamic typing will dilute its effectiveness, even if it is only perceived effectiveness. Its like fighter with short hands trying to fight outside fight… It will get knocked down by fighter that knows his identity.
Rob Conery on his blog has also some good points against this as well, but opposing voices have never stopped Microsoft in past so they will not this time either…
On the bright side, maybe this is how new and better things get born. We have to first destroy the good things we have today…
I think this is a really great analogy. Mostly I used VB.NET but do some Projects in C# but I have been wondering where Microsoft are heading with C# – it seems to be too many features with as you have emphasis a lack of identity.
In contrast I used Python a little bit last year and like it or lump it Python had a nice clear identify and got you up and running quickly.
Thanks Norman, that is what I thought would be fitting analogy after I heard about all these “latest and greatest” features being added to language… I hope I managed to express my thoughts, if not eloquently, then at least in general idea 🙂
I think the reason that these features found their way into C# is because the CLR needed support for these features in order to support functional programming and dynamic programming languages. In other words, if F# or IronRuby were going to be possible, the CLR needed to be enhanced. If the CLR has new capabilities, why not leverage them from C# or VB.NET? I would rather all of the .NET languages have the same capabilities than to have certain tasks that can only be accomplished in a certain language. If they are used appropriately, they can be pretty powerful features. I agree that the overuse and misuse of them will make code harder to read and the language harder to learn.
I agree that dynamic is a bit inconsistent with the strategy so far, and that if they’d like to create a scripting dialect of it they should do that directly.
I disagree that LINQ is bad. LINQ is perfectly strong typed, even lambdas and anonymous types are perfectly strong typed. There no way to ‘make a framework’ dependent on the ‘var’ keyword either. It’s a shortcut to typing something like IQueryable<SomeKrazywrpperFor>> which I think is perfectly acceptable.
I don’t see anything at all wrong with LINQ, and it’s provider model. The ability to implement your own presents a uniform way to treat objects, even if you’re going to great lengths behind the scenes and getting the objects from memory, a file, a database, some xml service, or whatever. Nothing wrong with that. In fact, we had some other thing that was meant for that purpose too, ADO.NET, but it’s a lot bulkier and conceptually more difficult, and worse it encourages people to write ad hoc queries all over the place. LINQ to whatever at least acknowledges the fact that people should code against an interface and not a specific implementation. (Granted they do that particularly poorly in some places, but the idea is, in my opinion, the right one.)
If your real beef, which I can understand, is with ‘dynamic,’ then lets leave it at that. Var and linq do nothing to the identity of c# as a statically typed language, which I agree is one of it’s nicest features. (I happen to like lambdas too!)
Hi Dave, thanks for thoughtful comment. Yeah the dynamic is real beef, I’ve thrown others in since I saw people using these language features with disregard to context and need. LINQ is neat, granted, but so is SQL and we learned that we need DAL on top of it. I am wondering do we end up with something akin to DAL for LINQ due to all abuse? 🙂
I’m very disappointed with the direction of the dynamic languages these days mostly because it seems like the designers don’t even try to include the benefits of static analysis. Here’s what I mean:
JavaScript allows you to create new classes of objects at runtime. All you need to do is create a constructor, and then add functions to the constructors prototype property (Think JavaScript’s VTable). I like this. What I don’t like is that you, or anyone else, can then delete or replace methods for that class. This is aptly called monkey patching, and I find this to be a horrible idea and practice. The reason people monkey patch is because they want to extend intrinsic objects, like integers and strings, with their own home brewed methods. I’m sure you can see how this is a recipe for a lot of bugs when you start mixing libraries that are all monkey patching the same intrinsic types.
I believe that creating new types at runtime is a good thing and it should be as easy like it is in JavaScript or Ruby. What I think is an awful idea is allowing programmers to mutate those types at runtime. (Generally, I find mutations to be the root of a lot of evils) If you can extend an intrinsic type, and then tell your language: “For this block of code, I want you to use this type for all integers rather than this built-in integer type”, then you’d avoid these errors and open up the door for creating really cool DSLs.
So, now that you’ve eliminated the need to modify types at runtime, you can start doing some of that compile-time, static-analysis, whenever you create a new type at runtime, because you know it is sealed and everything it depends on is also sealed. This allows you to do all sorts of neat and exciting things in terms of optimization and flow-analysis.
Hey Steve, that is a good point. Thank you for adding to the discussion.
Do you know how the var keyword works? It doesn’t remove static typing at all. Either does LINQ and Lambdas. I use LINQ all the time for things like searching lists or mapping lists. These features make some of the fundamental work I do every day MUCH easier. Think of LINQ as just a library toolkit for working with lists of things. Beyond that, the only thing that makes up the feature is the compiler turning turning query syntax into extension methods, which are really just static methods.
Do you have anything against static methods or delegates? That’s all the new 3.5 features are.
I DO understand your fear of the dynamic keyword, and you may have a valid point. I honestly haven’t made up my mind on that one yet. Don’t group “dynamic” in with var, LINQ, and Lambdas.
Hi Jason,
Yeah I know what is and have used var “typing”, LINQ and Lambdas. It is abuse of these that I saw, that made me lump them all together. For example. if you use var everywhere I think you are doing something wrong and I think it significantly reduced the readability of the code. I know compiler will treat that just as if you have implicitly typed it, but readability explicitly suffers…
I strongly disagree. Of course, like Dave and others said, there is nothing wrong with var, LINQ, lambdas, and anonymous types, so I won’t go into that.
However, everyone else seems to share your fear of the dynamic keyword, which I do not. Since the dynamic keyword is strictly an opt-in feature, it is the developer that must choose to use it. And if they do, the only real benefit they gain is by using it against libraries or other bits written in languages like IronRuby, IronPython, JavaScript, etc. Trying to do that in C# without dynamic is extremely painful.
If a developer decides to use the dynamic keyword against strongly-typed .NET code, they are shooting themselves in the foot because of the performance hit and lack of ability to do any kind of compile-time checking, as well as losing productivity due to lack of intellisense. In other words, *they are a bad developer*, not the language is insufficient or losing its identity. C# is also getting optional parameters, which VB has had for a while. They are very helpful when used correctly, but even with .NET 3.5, if someone was writing an app in VB and created a 500-line method with 40 optional parameters, they would be a *bad developer* too.
There is a point where you have to blame things on the language, sure, but here I feel that you would have to blame misuse on the developer. Likewise, I think there are great uses for this when used correctly, and they will create interoperability for the future which will help the language last longer, not shorten its life.
Paul, thank you for adding to the discussion. One thing I want to say is that this post is meant to provoke thinking about what happens to languages we use.
Programming language is defined as much by features it includes as by the features it excludes. In general, I do not think that programming language features are good or bad, but developers make them as such. It is this usage that “ruins” the language so it stands to reason that we should limit what gets included to avoid this “bad” behavior.
For example, we (developer community) learned that automatic memory management is “good”. We learned that raw access to memory through pointers etc. is “bad”. So that gave a raise to managed languages. I think that was good for everyone. Now, these features are not good or bad themselves, but usage of them makes them as such. Does that make sense?
I don’t mind “var”; it’s strongly typed. I would rather have c++ style typedefs though. It would save me a bit of typing and would make generics more betterer.
Bjarne Stroustrup once commented that the reason for Java’s popularity of C++ was that it didn’t yet have all the features that it would eventually need. He accurately predicted the bloat in Java and one could apply the same comment to C#.
The reason C# is better than Java is that Microsoft is letting the language grow thereby preventing it from stagnating like Java. Worse, it seems to me that the Java team is trying to bend over backward to make sure the syntax doesn’t mimic C++ or C#, even though the designers of those languages have already run into the same language problems, analyzed them and solved them correctly.
C# is doing a good job at replacing C++ as an overly complicated and hard to learn programming language.
VB.NET is not doing a such a good job at replacing VB6 as a beginners and hobbyist entry into programming.
Hasn’t C# always supported dynamic invocation using reflection? I understand there’s additional support under-the-hood when using dynamic but it’s effectively no different to getting the type of an object at runtime and calling InvokeMember in earlier versions of C#.
“C# will get diluted with so much unnecessary language features that nobody will want or like to use it effectively. I don’t think we need all this LINQ, Lambda, var typing and least of all dynamic keyword…”
Actually, I have to strongly disagree here. I must have read the article too fast, because I totally missed this sentence the first time around.
First, I’m a huge fan of LINQ, lambdas, and var (type inferencing) and have been using all three very extensively in my applications to dramatically simplify a lot of old code. At my company, we took to playing a form of code golf where a lot of the time we were reducing stuff by a factor of 10-1. If there were any features to leave in the C# language, I would leave these in and get rid of a lot of other stuff.
Let me explain it this way. LINQ is not another flavor-of-the-month technology that’s just for doing database queries, nor is it limited to doing database queries. LINQ is based on a fundamentally powerful abstraction called monads. (Monads are objects that represent computations and workflows, not data.) Unlike other fleeting design patterns, a monad is a very abstract and very fundamental mathematical concept that enables you to design complete systems by combining simpler complete systems. (Ex: A complete system might be addition where any_number + any_number always yield a number. An incomplete system would be division, where any_number / 0 (a number) does not yield a number, but something undefined.) Conceptually, you can imagine monads allowing you to combine integer addition rules, with signs (positive, negative), yielding a complete composite system of the two simpler systems. You can think of a complete system as a system that yields no unexpected behavior, while an incomplete system may yield unexpected behavior. Monads enable you to combine these systems that work, to create a composite system that also work. It’s subtle, but powerful.
If you haven’t downloaded LINQPad, I would recommend it you do this ASAP. Even if you have no interest in LINQ, it’s an excellent snippet compiler/executer (Intellisense costs $30, and I believe it’s worth it). Nevertheless, you should download it, go through the samples, and keep an open mind. Even if you’re not going to use LINQ to SQL, you should at least be looking at LINQ to Objects, because there is a more LINQ coming like Parallel LINQ, LINQ to Events, and much more.
Ok, so back to defending these features. As you may know, our processors have reached a limit in terms of clock speed for the past few years, and chips are now going multi-core. What’s your plan for writing applications so they can take advantage of multiple CPU’s? Are you going to spawn off some threads/processes yourself and synchronize them with semaphores, signals, critical sections, and mutexes? If you are, good luck writing your own multithreading code. I hope your bugs don’t result in some nice race-conditions or dead-locks.
I know when I’m going to write parallel code, I’m not going to waste my time writing my own plumbing code if I have an extensible library available. So, I’ll probably use Parallel LINQ when it becomes available. Likewise, when it comes to writing code that needs to enumerate, filter, correlate, group and sequence enumerations, I’m going to use a library that I know works, rather then write that code over and over again.
Like I said before, I agree with your general sentiment that C# is becoming a bit bloated, and I too, am not too excited about the dynamic keyword (because I believe it goes against Microsoft’s shift towards functional programming), but I do think that LINQ, lambdas, and type inferencing are definitely an exception as they are critical. In either case, simply letting C# to sit and rot like COBOL is not a good idea these days. There are simply too many good programming languages out there vying to replace the Java’s and C#’s of the world.
What it all boils down to is how the features are used. A good programmer knows that a language feature is just a tool, and like any tools some will be better than others for different tasks. To disregard a language feature because you think it blurs the identity of a language then I think the you either 1) Don’t realize what that particular tool is truly used for or 2) Don’t realize that no matter what tools a language offers, a bad programmer will likely use them wrong. But that doesn’t make the tool bad, it means the programmer has a thing or two to learn.
Personally, I think that C# identity is that it is a language where the language itself does not get in the way of the job that the programmer wants to get done. Originally, this was accomplished through a simplified syntax and managed code. When .NET 2.0 came along, this meant generics and support for delegates. 3.5 we got LINQ, lamdbas, anonymous types, automatic properties. Note that in each case the result was the programmers ability to write less code in a cleaner more-to-the-point manner. And, IMHO, *that* is C#/.NETs identity.
The var keyword has been a hot topic in this post, and elsewhere. Should it be used everywhere? No. But can you imagine trying to use the great features of LINQ and anonymous types without it? No. You’d have to drop back to reflection for even the simplest operation of accessing a public property. These two features (var and anonymous types/LINQ) are closely tied together, and of great benefit to the language. With LINQ, I can write more readable code. Does that mean we should use var everywhere? Absolutely not. But because we *could* use it everywhere does not mean we should use it no-where and drop it from the language.
The same can be said about the dynamic keyword. It will work fantastically for COM operations. And for interfacing with Ruby or Python, or other dynamic languages. In fact, by your very argument of identity we can state that the ability to interface with the dynamic languages easier from C# *helps* it keep its identity, because now people will be able to delegate tasks better suited to dynamic languages off to Ruby or Python without shoe-horning them into C#.
People have been abusing language features since the dawn of programming languages. But the ability to abuse them does not mean we should not have them.
In short, C# identity, to me, is it’s ability to write clear-concise code that just gets things done without the cruft of C++ or the verbose shackles of Java. And this means having features like lambdas and var and dynamic typing, so that when they are most appropriate they are there for us to use.
BK:
The fact that C# don’t support something like C++ typedef is intentional. There’s really no need for it. Typedef in C# might save you some typing (but not much) but it would make the code less readable. Using typedef for basic types like int, decimal, etc just hides from you what are you working with. Sometimes the idea is “let’s define Price as double, maybe later we can change it to decimal”. But this is stupid because if you eventualy decide to change it from double to decimal, you still should go thru all the code that uses the Price and see if it’s ok.
By renaming something “ugly” like List<KeyValuePair> you are again just hiding what the thing is. If it’s really something complicated and there is a good name for it, you can create a subclass of it.
[…] previous post about C# losing its identity, “You Have To Know Your Identity” sparked lots of good discussion, which was my intent. There are very good comments in that […]
you guys see nemerle and then forget about C#.
Robo:
I agree with the examples you’ve given. Clearly those are the wrong reasons to use typedefs. I am thinking more about generics. With C++ templates, using typedefs to refer to a type you expect the parameterized type to define is powerful technique. Without out it, I have to use reflection (blech) or just make my C# code unnecessarily verbose. If introduced typedefs, but restricted them to generics, I would be plenty happy.
-BK
Robo (redux):
Please allow me to refine my last comment: It would be nice to have typedefs for redefining types within classes for use within generics.
BK