Deep Dive Into C# 9
c-sharpcorner.com
c-sharpcorner.com
I really enjoy the language and the functional features that seep from F# are great. Right now C# is my goto language for fast prototyping of anything really. At this point I trust Microsoft to push the language in the right direction.
EDIT: A bit more detail and typos
C# is a great language indeed.
Constructors are a design pattern that works and is intuitive at this point. Fair enough there are differences, but the overlap in use case is significant enough that I don’t think it warrants a rival implementation of a core language feature.
The irony of me complaining about it is that I’d much prefer we get proper object composition by letting extension methods support extended state, which would rival dependency injection in its current form.
This would overturn the apple cart even more but it’s long overdue - I implemented this years ago by using conditional weak tables but didn’t trust it even in my own work solely because if MS isn’t standing over the implementation then I’ve no way of knowing how the GC is going to handle orphaned references over time.
Example:
A car has five (obvious) wheels, only four of which have tyres and rims.
Modelling this from interfaces and injected dependencies on a parent class is a laborious anti-pattern that C# still forces me into.
I love C#, but this could be so much better.
It's kind of agreed that object composition is a design goal we should be reaching for but are stopped frustratingly short of being able to compose objects from smaller components directly, so the design has to be top-down (class-based inheritance) rather than bottom-up (object composition).
It's also cleaner than dependency injection as you wouldn't need to pre-specify what a class hierarchy can or cannot be composed of at top level.
If composition isn’t implemented as a core language feature and officially supported then I’ve no way of knowing exactly how my implentation will behave or perform in the future or if there will be breaking changes down the road that render the foundation I’ve built all my code on moot.
The syntax looks outright ugly in many examples.
It's been an... interesting ride.
Now, for someone new the features set, the various keyword overloads and the magic syntactic sugar can make it hard to tame. Back then, It was mostly a (slightly) better Java. It has evolved into something totally different, that often tries to mimic F# while still keeping the familiar curly-race syntax, which makes things awkward at time. C# is my main language, but sometime I feel like there should be a fork, with a legacy C# that keep being ported to new frameworks and platforms, and a new branch where feature creep can continue go wild.
You don't have to use language features you dislike. If you want to prevent them being used, you can set the c# language level to an old version using the LangVersion element in your csproj file.
if working in a team, your team members are unlikely to thank you!
For us, the language features we can use internally are dictated by our own compiler to translate the code to JS and Java and yes, a null check is somewhat verbose compared to ?., but in such cases it can be important to restrict the language level, even if you could locally use a newer one. We're also, for compat reasons, building the code on the build server with basically VS 2010 to ensure that there's nothing in it that .NET 4.0 can't handle. Customers can sometimes be very_ conservative and value this kind of thing.
If you want to prevent them being used, you can[0] set the c# language level to an old version using the LangVersion element in your csproj file.
[0] if working in a team, your team members are unlikely to thank you!
It’s like that with a lot of our systems, and it’s pushed us more and more from C# to Python where a lot of things are just easier.
We had similar issues with the AD APIs in .NET. You’d think Microsoft would have extensive AD integration support for C#, but you’d be wrong. It’s nothing you can’t fix by overriding the standard libraries with extensions of your own, but it’s a lot of work. Which is kind of the opposite of why you’d pick C#. At least in my opinion, you pick it because it comes with a powerful IDE and powerful standard libraries, but it turns out that it doesn’t actually do that once you dig a little deeper than standard CRUD applications.
Either you freeze the language and let it stagnate or you keep adding features without removing them and suffer from bloat.
Seems like the slow churn of high level languages is inevitable while maintaining backwards compatibility.
I feel like there’s probably a good analogy with evolution of human languages and cultures around them. How many of us can read Beowulf in the original?
I think it helps a lot if you use Rider, or Visual Studio with ReSharper, as they will automatically make suggestions to use new language features when appropriate - that way you always get exposed to new syntax.
I completely agree - I rather like how C# and .Net is progressing - sure there are new features every so often that take time to learn but isn't that the same for absolutely everything.
I do agree that the syntax proposed thus far for records and discriminated unions is far from pretty, but I can't see it making it into the spec like that.
I think these days you must force a specific code style according to a specific C# version otherwise you're going to have a mess. Harder to read for those used to older c# version while also hard to read for those used to newer c# versions.
You can have a valid reason to have c# classes that just use lambda to implement interfaces, a valid reason to have an interface with methods implementation, and a valid reason to do classic c#. In the end, you still have a mess.
I hope that someone makes a tool that helps make the code consistent and let developers avoid the suffering of thinking "but why is this like this??? oh wait... this the other c# version feature which I never used before.... I guess it's okay? ¯\_(ツ)_/¯
C# still has a lot to go to catch up with C++, on the language level.
On the other hand, contrary to common beliefs regarding C++'s complexity, no one is able to master the complete standard library of either Java or .NET, let alone the major frameworks that also get used alongside them.
The only thing about Java that I really like is that you can not use it in it's ecosystem while not feeling like a second class citizen. Kotlin (I didn't use the other JVM languages so far) feels 100% supported while F# in Visual Studio is kind of rough.
Java itself: hope I never have to work with it.
Platform languages always win long term, adopting what matters from guest languages, while exposing the platform without any additional FFI, IDE plugins, build tools, idiomatic wrapper libraries, new layers to debug,...
C# was once a great language, but today it is so bloated with features that there is no clear way anymore on doing a single thing. Everything in C# has 3-10 different ways of doing it with huge BUTs, making the language harder and harder to learn for beginners.
It doesn't even make sense to make C# more funcitonal. It's trying to be too many things at the same time. It's almost like an obsession which Microsoft has with C#. Everything great they see somewhere they just shoehorn it into C# and actually really harming the language. What happened to just being a good OO language. .NET already has two other languages, one is functional and you can use F# and C# side by side in a project. What is the purpose of mudding C# to a point where nobody really knows anymore how to write clean and good C# code?
Honestly, I see C# developers constantly re-writing and re-designing their code for the sake of rewriting because there's constantly a new way of doing something. C# developers are like Java developers, spending so much time thinking how to write a feature instaed of just getting on with the work.
.NET Core is great, but .NET, C# and Microsoft in general is still the same old shit plagued by the same old MSFT mindset.
If developers want to write great applications then choose anything but .NET (Core), because in C# you'll constantly be chasing and re-writing existing code because things change for the sake of changing without really making the application any better.
.NET Core itself and ASP.NET Core is still changing so much that it's just tiring.
I think the big changes between .net framework and . Net Core weren't that big for a project.
And it got a lot faster.
Are there any popular application programming platforms that are widely used that haven't evolved fairly rapidly and caused a lot of complaints along the way?
It's two philosophies: 1. Backwards compatibility is king, 2. The best framework possible is king. #1, over time, can lead to a hot mess.
I am yet to get a RFP that even mentions it.
I know a lot of companies that really want to run away from a dependency on Windows - especially in cloud environments. Every time you introduce Windows into the mix it costs more for licenses and resources.
This is coming from someone who has exclusively developed and deployed to Windows servers until 2 years ago and even now my only Linux deployments are Lambda and Docker.
Better pay attention to MS conferences then, they have stressed multiple times that VS is going to stay .NET Framework and how they are commited to keep it as long as there is Windows.
And at .NET Core 3.0 release conference it was visible in multiple occasions how they are fighting the re-writing fatige from many enterprises.
I think JetBrains knows a little about the .Net ecosystem.
https://www.jetbrains.com/lp/devecosystem-2019/csharp/
As far as cloud and server adoption.
https://www.makeuseof.com/tag/linux-market-share/
On Amazon EC2, standard Linux (along with its various distros) controls 92 percent of the market. It boasts more than 350,000 individual instances. Again, Windows is responsible for the other eight percent.
Even MS said that 2/3 of their VMs on Azure are running Linux.
Those VMs running Linux is where we put our Java stuff not .NET.
Just like my anecdotes are the sample of our DAX and Fortune 500 customers.
Linux adoption? Yes it is wiping Windows on the server, that is why I always worked for Java/.NET shops since 2006, switching stacks as per customer project requirements, in some projects even both get equally used.
Somehow your replies always feel being about fear of using outdated tech, always having to jump into new toys to keep being employable.
Never felt the need to worry about that, as long as we have happy customers, opportunities abound, regardless of what is the latest tech stack fashion.
I think JetBrains sample size is a lot larger than yours.
.Net Core isn’t “new”. It’s been around since 2016 and the direction that Microsoft is headed in.
never felt the need to worry about that, as long as we have happy customers, opportunities abound, regardless of what is the latest tech stack fashion.
And what happens when either you want to or are forced to change jobs? Someone who is 40+ will be seen as just another old head who hasn’t kept up with technology and be on HN screaming about “ageism”. Not directed at you personally. I’m also in my mid 40s and seen it happen time and time again. Someone staying at a job for 20 years and then gets laid off and all they have to offer is that they are really good at ASP.Net WebForms when the world has moved on.
Heck it happen to me at 35 looking for a job and my experience after staying with a company for 10 years was VB6 and C++/MFC.
Instead of moving on to technologies that are in the “slope of enlightenment” phase of the hype cycle would you suggest that I kept doing C on DEC and Stratus mainframes like I did on my first job?
The average tenure of a developer in the US is 3-4 years.
And yet most of those RFP keep referring to stuff like .NET Framework 4.6 and .NET 4.7.1.
As for the job, luckily Europe is not as bad as US in what concerns ageism.
Over 40 here as well and so far no problems switching jobs, because I always strived not to be labelled as only being good at technology X, without anything else to offer.
My advice is to diversify domain knowledge, master soft skills, be able to jump between developer, QA and technical lead roles across delivery sprints, and most customers will find less relevant how well one masters the very latest version of technology X, rather what is the business value one brings to the organization.
And some of them, do value a lot that one is able to keep that old clunky VB 6 application running, instead of sinking several thousand euros attempting an half-baked rewrite into the latest stack trend, and do pay accordingly as well.
And yet again you use your own anecdotal evidence without any large sample size.....
As for the job, luckily Europe is not as bad as US in what concerns ageism.
So how competitive is someone all other things being equal who hasn’t kept up with technology as someone who has?
And some of them, do value a lot that one is able to keep that old clunky VB 6 application running, instead of sinking several thousand euros attempting an half-baked rewrite into the latest stack trend, and do pay accordingly as well.
Until Microsoft introduces an operating system that doesn’t support it and you’re stuck with an unsupported OS with an unsupported runtime with security and compliance concerns.
If they get the job of their dreams, it is a completely different matter though.
I am angry that .NET Core keeps changing faster than Kim Kardashian changes her outfits. First they focused on making .NET Core all about ASP.NET with a clear focus on MVC and making everything super granular. Then they didn't like how granular it was and started to put lots of featurs into smaller pacakges again. Then they keep re-inventing things. First introduce Newtonsoft Json into the default .NET Core stack. Then rewrite everything. The webhost model keeps constnantly changing. The ASP.NET Core team now is realising that people hate MVC and they are splitting out more features from MVC into more basic ASP.NET Core features, which is why routing has completely changed again with endpoint routing. Honestly nothing is constant, not even for 6 months. Every version of .NET Core almost requires a developer to completely rewrite their Startup.cs class. It's just ridiculous.
The reason for all of this is old MSFT thinking. It's not bloody rocket science, people have been saying it for years that they don't want to be forced into MVC, they want things to be more lightweight, bla bla bla. But obviously MSFT cares more about making a shit hello world demo at BUILD and therefore they first must hack together ASP.NET Core which was mostly just about MVC before being allowed to build the core platform to something that is actually useful to others.
They'll constantly keep changing the fundamentals, moving the carpet under developers feet and distracting businesses with stupid useless excercises or rewriting shit instead of just creating a stable base platform on which people can freely build applications and actually focus on their own apps.
"First they focused on making .NET Core all about ASP.NET with a clear focus on MVC and making everything super granular. Then they didn't like how granular it was and started to put lots of featurs into smaller pacakges again."
.Net core was a ground-up re-write and was the vehicle used to opensource all .Net. It was always meant to grow into a full-scale offering and eventually bring along all the features users demanded. I personally love reading all the fun library code: https://github.com/dotnet/runtime/tree/master/src/libraries
" First introduce Newtonsoft Json into the default .NET Core stack. Then rewrite everything."
Newtonsoft itself is bloated and there is no turning back for that library. MS is providing an option to use a lightweight JSON library that uses the new SPAN ref struct.
"The ASP.NET Core team now is realising that people hate MVC and they are splitting out more features from MVC into more basic ASP.NET Core features, which is why routing has completely changed again with endpoint routing."
Endpoint mapping wasn't born out of hate for MVC, it facilitates the separation of framework/transport/protocol without introducing config files (or handler code) for each. https://github.com/aspnet/AspNetCore/issues/4772
"The reason for all of this is old MSFT thinking. It's not bloody rocket science, people have been saying it for years that they don't want to be forced into MVC, they want things to be more lightweight, bla bla bla."
Maybe I am old but I remember when MS was almost forced to adopt MVC. They kept webforms alive for a long time. They introduced razor pages when SPA world demanded an easier solution. I am not sure if there was going to be a way to satisfy everyone here.
That means you don't have to update for a very long time ;)
The name changed and there is an obsolete attribute on it with instructions.
> First introduce Newtonsoft Json into the default .NET Core stack.
With the same usage/properties/methods but faster
> routing has completely changed
Another method, the older one is still available ( also, obsolete attribute)
> completely rewrite their Startup.cs class
Wait what? You already named 2 of the 3 changes and there is probably a year in between. Also, the third change is related to the webhost change.
Kim changes every day
C# has become a great language for the "functional core, imperative shell" way of doing things. That means it has to be a hybrid language. F# is more tilted toward functional-land, C# is tilted toward imperative/OO-land. Both have their place.
If C# devs are constantly rewriting their code, that means there's no vision for that particular codebase. It's true that there are many different ways to "do C#." So, a developer or team needs to pick a particular way (OO classic, or functional core/imp shell, or functional, or minimal golang-style) and stick to it. It's more of an architectural challenge than you would get with a language that can only do one of those. The upside is, your system can blend approaches as necessary, all within one codebase. Every module of the system is perfectly suited to its task, from philosophy all the way down. Of course there's the danger of it becoming a mess, but the risk is worth the reward IMO. With great power comes great responsibility as they say.
If something can be written in 10 different ways then it will be re-writting in 10 different ways, because today you are leading your team and defining 1/10 ways. Tomorrow you leave and another lead or senior comes onboard and will disagree with your architecture and then slowly re-write everything.
Even worse, every time you add a new person on your team there's a 9/10 chance that they will disagree with your code. Your team will waste so much time between people just talking about how to write something because people get hung up on minor details instead of just trying to build a good application solving a real problem. The micro benefits of doing something in c# one way or another are in 99.999% of applications a complete waste of time.
Whenever I'm trying to hire C# developers (something I've been doing a lot over the years) I'm amazed how little people even know about C#. There's literally so much when you go deep that most people are completely clueless and it's getting worse and worse.
A wise lead may prefer a different path to their predecessor but respect the decisions that were made before them and realize that it's counterproductive to chaotically "drip-migrate." And good experienced developers will not get bogged down in endless debates with no clear winners.
It just sounds like you've had some bad experiences.
A general rule is you made modifications to a codebase the same style / technology as the original codebase. I've seen bad developers not do this and it certainly turns into a mess.
MSFT stacks are an ever ending wild ride of change, deprecation, constant direction shifting and bugs.
I’ve been writing c# since 2002 and I’m quite frankly done now. It doesn’t help me solve problems now. It just creates new ones I don’t want to solve or have to pay to solve.
The IDE is buggy, the platform is buggy and the churn is so bad it’s a ridiculous prospect trying to build a non trivial business on it now.
Most companies are still stuck on classic .net because hardly anything is really portable to core. On top of that when you do finally drag it to core 2.2 then it’s deprecated so you have to rewrite half your MVC stack for 3.0.
And then there’s the customer abuse like opt out Telemetry.
2.2 to 3.1 is probably the easiest upgrade I’ve ever done. You wanna talk about mvc 1 to 2/3, now that was a painful upgrade.
I feel sorry for new Developers because I learnt those features bit-by-bit over the years and they are expected to learn them at a go. It is also hard to understand why a syntatic was introduced when you never used the way it used to be done.
I also use Resharper, it repeatedly reminds me of new syntactical ways of doing things.
I understood from a Microsoft conference I attended (regrettably I forget the speaker) that their decision to incorporate new features so rapidly was a very conscious decision, based on what I thought to be a quite perceptive look at the landscape - to some extent C# has always been a reaction to Java; a language that often comes under fire for its extremely slow and cautious incorporation of features.
The world's best OOP-system (CLOS) was conceived using macos.
I see this in Scala, not Java, as the latter's feature set is much more restricted.
Every language seems to start out as a crisp new tool for solving a well chosen specific set of problems. Then over the years with each release a new set of use/edge cases get covered by introducing new concepts and syntax. And while each of these has its own merits, in aggregate they turn the system gradually into an unapproachable behemoth of opaque incantations.
And so the wheel turns and we all start over the process with a crisp new language that targets a well chosen smaller set of use cases ....
Programming languages are software products as well, and to stay relevant they need to cover use cases that make developers "buy" them.
The new languages are simple like original languages started out but with a different set of simple principles that have learned about from the previous generation.
Languages are just as much about they exclude, as well as what they include.
I'm specifically using 'system' as opposed to 'language' as reference to not just the core language syntax but including the canon APIs knowledge needed to claim a proficiency in developing in the language's ecosystem.
e.g. Compare how classes and objects work in .Net with CLOS and its MOP.
CLOS is a topic on its own. I loved it myself, as for me it aligned much more with the way my brain wrapped around an object paradigm and I felt the dispatching in what became a more traditional object approach from Smalltalk to Java and C# to be way too restrictive and therefore needing to resort quaint constructs for pretty basic composite things. But I do know this was not the most popular opinion.
And there are languages that are deliberately conservative about adding new features, like Go, Elixir and even Python to some extent. Though I think Go is too far on the other end of the spectrum, I always prefer languages with a small, simple core.
C# seems to just constantly throw everything new in.
But hey, some seem to prefer to have all these different ways of doing things and I'm not the one to tell them what to like or not. I don't have to use C# myself.
(Non-)nullable references are a perfect example. They could have been supported on the old .NET Framework, but MS chose to only officially support them under .NET Core (will be .NET 5 soon).
I have a library that is used in both "legacy" (.NET Framework, never to be ported to .NET Core) and "new" (.NET Core or soon-to-be .NET Core) projects. It makes perfect sense to annotate it for nullability and it doesn't need any of the other C# 8 features that depend on .NET Core. But I can't (officially) do it, even though Mads Torgersen himself wrote:
https://devblogs.microsoft.com/dotnet/embracing-nullable-ref...
You also have to set the language version to C# 8.0, of course, and that is not a supported scenario when one of the target versions is below .NET Core 3.0. However, you can still do it manually in your project settings, and unlike many C# 8.0 features, the NRT feature specifically happens to not depend on specific elements of .NET Core 3.1.
F# should be Microsofts main language, not C# It's a great language that doesn't get enough attention IMO.
In fact, I think F# is a better imperative language than C#, if you choose to use it that way.
We need more of the likes of "System.IO.File.ReadAllLines()", one liner functions that take care of the most common things. Like if you want to encrypt with AES you need a 8-10 lines of codes, if you want to convert a byte array to a hex string or do case insensitive string comparisons, you need to create your own helper functions, etc. Until recently there was no json serializer out of the box.
For some of the features mentioned here, I can only wonder how many developers will really use them, while the cost is to make the syntax even more cryptic to a beginner.
Funny part is VB.NET gas had that for a while
There's no turning back. People will soon find they need more and more type operators, generics, and all kinds of type-level things. Each concrete operator or construct solves several specific type problems, and then introduces new ones. Until people realize dependent type is a thing.
I never understood why readonly did not allow during initialization, especially since initializing values is often used in place of a proper constructor, and is understood to be something that happens at construction.
But there must have been a use case they were targeting that I'm just not familiar with.
When I first tried to use readonly, I actually expected it to behave the way initonly would now.
Being able to compare memory to compare two object doesn't make an object any lighter, compared to magically calling a compare method on the object itself (can be decided at compilation time, thus no performance penalty: it depends on what the compare method does.)
Immutability also doesn't make the object lighter, it's again a compile-time property.
I am still missing something...
currently records are more comparable to the scala case classes, where you have automatic destructors, better equality, immutability, etc... and not necessary a compacter memory data.
reading the proposal makes more sense than this deep dive, since it explains the reasoning why they don't added special cased data classes.
Records automatically implement them. So its lightweight in that you need less code.
But e.g. native ints will most likely require CLR update since I assume you can use native ints with reflection.