back to article The evolution of C#: Lead designer describes modernization journey, breaks it down about getting func-y

C# lead designer Mads Torgersen cracked open a window into the evolution of the language during his spot at the virtual QCon Plus developer conference last week, and was quite frank about what has worked and what has not. The programming language is "about two decades old," said Torgersen, "and during that time it's [gone] …

  1. Mike 137 Silver badge

    Full circle?

    'Object-oriented programming focuses on encapsulating functionality and data together," but in this new world, "packaging the functionality with the data doesn't make sense any more. You need to have the functions on the outside," by which he meant, "you need to write a function that takes some object in, the object doesn't know about the function, but the function does different things depending on the type of the object.'

    Sounds like we might need a good "old fashioned" procedural language for this - something like C?

    1. Tim 11

      Re: Full circle?

      I'd disagree. From where I sit, functional programming is all about immutability and avoiding side effects, separating the function from the data; whereas OO is about encapsulating and mutating state. In many systems there is a place for both, and C# is trying to allow either paradigm to be used.

      A non-OO procedural language like C is IMHO just an inferior option to OO - it's mutating state but without the encapsulation that OO offers.

      Just my 2¢

    2. StrangerHereMyself

      Re: Full circle?

      Not true, since languages such as Rust have Traits with much of the capabilities of OO but with much lower abstraction cost. It's much more than a function which passes a pointer to its struct as the first parameter.

      C# is trying to go the same route, but keeps toting its OO baggage with it.

  2. Torben Mogensen

    "You can't take anything away"

    While it is traditional to not remove features from a language to ensure full backwards compatibility, there are ways around it:

    - You can make a tool that will transform programs using the deleted feature into some that don't. This can require a bit of manual work, but not too much. Of course, fully automatic is best.

    - You can remove the feature from all future compilers, but keep supporting the last compiler that has the feature (without adding new features to this).

    - Warn that it will be removed in X years, and then remove it, in the meantime letting compilers warn that the feature will disappear. People will then have the choice between modifying their programs or use old, non-supported compilers once the feature is gone.

    - You can introduce a completely new language that is only library-compatible with the old, let the old stay unchanged forever, and suggest people move to use the new language. This is sort of what Apple did with Swift to replace Objective C.

    1. Blackjack Silver badge

      Re: "You can't take anything away"

      This is Microsoft aka the "We keep compatibility with old things until we really can't." Company..And "If you are an Enterprise customer then we do it even then."

      Heck For Enterprise customers Internet Explorer won't die until five years from now.

      What can you expect from a programing language made from a company that brags that Office 95 still runs on Windows 10?

    2. MacroRodent Silver badge

      Re: "You can't take anything away"

      For the language user that is in charge of large source bases, all the alternatives you list are just a menu of torture methods.

      As long as a language is just a research project, or used only by you and your pals, you can do incompatible changes. But when you start getting questions from people you have never heard of, your language has succeeded, and it has a price. Either you commit to stability with all the mundane labour it entails, or do some of the above stunts, and receive enough bad karma and evil thoughts from your users to ensure you are reborn as a tick in the next life...

  3. Warm Braw Silver badge

    Breaking a lot: we can't do that

    Somebody put that man in charge of the .NET Framework/Core!

    It is rather impressive how C# has evolved, though I'm not entirely sure that things like dynamic types or LINQ are worth the trouble in practice, though they're undoubtedly significant technical achievements. I have similar misgivings about ORMs (like EF) - the superficial convenience hides a lot of implementation detail you might ideally want to control.

    However, this might partly be sour grapes on my part because they develop new features faster than my coding is capable of evolving...

    1. AndrueC Silver badge

      Re: Breaking a lot: we can't do that

      Oh I like LINQ. I don't love it but being able to project from one list to another using a single line of code(*) is nice.

      ThumbnailsForImages = (await _availablePictures.Select(async p => await GetThumbnailAsync(p)).WhenAll()).ToList();

      As long as you don't just assign the expression to a DTO property you'll be fine(**).

      Dynamics are occasionally very handy but aside from the performance issues it tends to leave an icky trail of compiler weirdness for the remainder of the code block.

      (*)Give or take line wrapping :)

      (**)Moi? As if I ever made that mistake :)

      1. StrangerHereMyself

        Re: Breaking a lot: we can't do that

        Yeah, lots of people have started complaining about the async-fetish within Microsoft.

    2. david 12

      Re: Breaking a lot: we can't do that

      ""People… have code they've committed and if you take anything out or change what it means, you're breaking a lot: we can't do that," "

      Which it's been right from the start, when they wanted people to move seamlessly from c and c++ to c#.

      And which is why VB.Net was such a fail. Because it was designed to be like c/c++/java, which largely changed what it meant.

  4. Torben Mogensen

    Functional C# == F#

    If you like the .NET platform and C#, but want something more functional, you could try F#. F# is sort of a merge of OCaml and C#, having most of the features of both, but works best if you program mostly in a functional style. You can use all .NET libraries, and there are some F#-specific libraries that better support a functional style.

    There are some places where having to support both functional and OO styles make things a bit ugly (for example two different syntaxes for exactly the same thing), but overall it is not a bad language. Not as elegant as Standard ML, though.

  5. karlkarl Silver badge

    "If you look at the world of games, the majority are written in Unity which is based on a C# engine that was..."

    A few incorrect statements here.

    Unity is written in C++ and provides .NET bindings like CryEngine does i.e Lua. You wouldn't say Crysis is based on a Lua engine would you? Statements like these do not help some developers grasp quite why C and C++ are still irreplaceable and have been for many many years. If people do not grasp this, we will never progress. Just look how long it has taken for something like Rust to exist for example.

    Obviously they are including amateur and student games in their figures because Unity has never really broken into the professional or AAA markets. So going by this logic I would suggest that "the majority of games are written in Adobe Flash". Simply by going with the sheer hordes of these things. I feel they are being a little deliberately misleading here. Perhaps Unity paid them a little bit of their gigantic evangelism budget here.

    Basically, if he stated this during a developer interview at our company... he would not have been offered a job. And that is before we even get into the technical questions ;)

    1. Martin 67

      "Obviously they are including amateur and student games in their figures because Unity has never really broken into the professional or AAA markets."

      True, it's not very popular, but some big games have used it, including Pillars of Eternity 1/2, Kerbal Space Program 1/2, Verdun, War for the Overworld, Final Fantasy IX, Tyranny, Endless Space 2, Escape from Tarkov, Sudden Strike 4, Wasteland 3, and some console ports (Pokemon, Sonic & Mario games)

    2. Kristian Walsh

      "Basically, if he stated this during a developer interview at our company... he would not have been offered a job. "

      And if that's in any way indicative of how your company conducts interviews, I think he'd be glad to have dodged a bullet...

      1. Ian 7

        "And if that's in any way indicative of how your company conducts interviews, I think he'd be glad to have dodged a bullet..."

        I was just thinking exactly the same...

    3. JDX Gold badge

      If your company doesn't want to hire the foremost expert on the language, I think this says more about your company.

      Also, you're still writing games in Flash?

  6. StrangerHereMyself

    A mess

    So Microsoft has unified .NET Framework with .NET Core, but the problem is that half the stuff from .NET Framework isn't working properly. WCF for example is only partially implemented in .NET 5. This means that many projects will be stuck on .NET Framework however long Microsoft keeps supporting it. The unification is in essence a failure.

    I used to explain other people .NET Core as the multi-platform version of .NET (runs on Windows / Mac / Linux) whilst .NET Framework was Windows-only. Now .NET 5 contains some parts which only work on Windows (Winforms, WPF) whilst others are multi-platform. I personally believe this sucks. I'd wish they'd kept the distinction between multi-platform and Windows only or ported everything to run on all platforms (possible, but would take quite some effort, but that's why the distinction existed in the first place, right?)

    I also believe the newer extensions to the language are merely to solve some very esoteric problems, or to make writing code for them less verbose.

    Also, I see more and more stuff from Rust (pattern matching) ending up in C#. How long before we start to see enums with values appear in C#? All this enormously complicates the language and turns it into a mixed bag which misses orthogonality. He himself stated that the dynamic stuff wasn't really helpful in a JIT language (and striving to be a AOT language) because of the overhead.

    I have the feeling C# has started to become an amalgamation of several languages (Java, functional langues, dynamic languages such as JavaScript and Python and Rust).

    1. deathchurch

      Re: A mess

      Ok grandad, time to move off WCF and onto gRPC. Why on earth would they go to the trouble of porting something like winforms to other platforms just to keep the luddites like yourself happy. Face up to it .NET Framework 4.8 and below are dead in the water, get everything ported to .NET 5 and beyond...

      1. StrangerHereMyself

        Re: A mess

        Because the stated goal of .NET 5 was to unify .NET Core and .NET Framework and if you do you must do it COMPLETELY or not at all. I myself haven't created a WCF project for years, but I ran into some fairly recently created projects which still used WCF (to my horror).

        The failure to port Winforms and WPF to other platforms is also troublesome. There has been some talk that they *may* port it to other platforms but AFAIK nothing's definitive.

        Look, I can relate with Microsoft for them not wanting to support two frameworks, but the way they did the unification is simply sloppy.

        1. Ian 7

          Re: A mess

          Mah, maybe, maybe not. They've been explicit about what they're porting across (e.g. bits of WCF, no WF), and the Windows-specific bits you have to opt into with appropriate target framework monikers. .Net Framework is still fully supported so there's no reason to kill off your old WCF services - you probably don't need to add much to those old services that's going to require all the new bits of .Net 5.

          It's a pragmatic choice; resource is finite, use it where the value is greatest.

        2. Steve Channell

          Re: A mess

          Winforms was ported by Mono a decade ago, but very few people are use it.

          There is a port of WCF to .NET 5, but does not include all the WS* options (e.g. WS-Transactions) that would require the porting of COM+ and MSMQ that would not be used anyway.

    2. Michael Wojcik Silver badge

      Re: A mess

      I like Rust, but it most certainly did not invent pattern matching, which goes back at least as far as ML. F# had pattern matching five years before Rust was first released. It's nonsensical to claim that C# got pattern matching "from Rust".

  7. Version 1.0 Silver badge

    Two decades of lessons that no one has learned

    Great article El Reg (hence the icon), and where are we today? We're seeing all of the issues described in today's languages and we're going to see them again in tomorrows languages.

  8. Ashto5

    Horses for Courses

    The question I would have asked him

    "Given a blank slate, what would you do now?"

    C# is great and has provided me with a good living for a long time, VB before that, Delphi before that and Cobol before that.

    When I look at what these guys and gals produce, I can see that I stand on the shoulders of GIANTS, I am OK with that :)

    1. StrangerHereMyself

      Re: Horses for Courses

      The blank slate WAS .NET Core. This is the reason why features introduced on .NET Core didn't work on .NET Framework, because the latter had to remain compatible with legacy code.

      1. Michael Wojcik Silver badge

        Re: Horses for Courses

        .NET Core is not C#. The article is about the latter, and that's what Torgersen is the lead designer for. .NET Core was not an opportunity to replace C# with something else.

  9. B33Dub

    C# Love

    Of all the languages I have to work with, C# is by the far funnest. I don't mind a challenge but here's an anecdote.

    I occasionally find myself working with Java and its like...

    Me: Ok I got this moderately complicated thing to do here, and I'd like to respect some OOP principals here. How do we do this?

    Java: LOL. I'll need about 20 interfaces and your soul.

    Me: Hmmm... I'll need some logic controlled "properties" on some of my objects. Can you handle that?

    Java: WTF is a "property"? I only got "fields". Just kidding I know what it is I just don't care. Yea I'll be needing some methods for that. Its ok, like our entire ecosystem has a naming convention and YOU BETTER GET IT RIGHT, like its "get" and "set" before methods, but in the case of booleans its like ... who knows? "is"? LOL. Good luck bitch. Fuck you we'll never express it in language. Muwahahahahaha.

    Me: Seems like a pain in the ass. Ok can I import some good repositories to make this simpler.

    Java: LOL fool, don't get me started. Good luck finding the packages you need to get things done. Hope you know what exact ecosystem you're working with because there's like SO many repositories. Make sure you got the right platform X architecture X operating system X phase of the moon. Also, make sure you don't typo anything because the hackers LOVE preying on moron programmers like YOU and no one cares about rooting out the bad actors. Bwahahahahahaha,


    Meanwhile, in C# land

    Me: Good lord, what is that 78 character generic type signature that this method is returning where I only need to store a MERE reference to it real quick?

    C#: No worries bro, just declare it as "var" and I'll infer that nonsense. Also, you can kinda use this to not worry about minor code changes in the future ;)

    Me: Hmm, need to do a call back. Time to declare an interfa ...

    C#: Hold on sir. Its fine. Just use the Action or Func types as argument types. One of those is surely ready to suit your needs and you can use a lambda for something anonymous or directly reference an existing member on any accessible class.

    Me: Great. This method needs an options object. Time to new it up and assign properties one by one.

    C#: There is an easier way bro. Pass the the object as new in the argument and use curly braces to set all of its fields (properties). Doesn't really change what's going on but its much more readable and concise than the alternative.

    (I could literally go on here about how C# makes most annoyances of OOP easier here, but I will cut it off).

    And then don't get me started when you add .Net Core into the mix.

    1. AndrueC Silver badge

      Re: C# Love

      C#: There is an easier way bro. Pass the the object as new in the argument and use curly braces to set all of its fields (properties). Doesn't really change what's going on but its much more readable and concise than the alternative.

      I'm not actually a fan of that part of C# syntax. What happens if you subsequently add another property to the object? I'll tell you - nothing at first because the code will compile just fine like it always did. Only when you, your QA guys or - heaven forfend - your customer actually execute code that depends on that object's state will things go wrong.

      However if you gave the object a constructor that took values for all the required objects and made the properties immutable you'd be forced to fix up your code to cater for the new property before it would even compile.

      Programmers are careless, they can forget to initialise properties. Compilers are not careless. They won't let you create an object without calling a constructor. They won't let you call a constructor without supplying all the parameters and they won't let you change properties that are immutable.

      new Safer(42);

      Is safer than:

      new Dangerous{42};

      1. AndrueC Silver badge

        Re: C# Love

        Lol, just spotted a typo.

        new Dangerous{42};

        Should of course have been something like:

        new Dangerous{ImportantValue=42};

POST COMMENT House rules

Not a member of The Register? Create a new account here.

  • Enter your comment

  • Add an icon

Anonymous cowards cannot choose their icon

Biting the hand that feeds IT © 1998–2021