It's in the same space as Java/Go, and .Net Core seems to be getting a lot of love on Linux. The recent 3.0 announcement shows some awesome performance gains and some sweet new features, including ready to run to reduce startup time, and moves toward AOT / single binary (although coreRT already does this?).
I have been working with C# for a long time now, so it's pretty cool to watch it become a contender in cross platform server-side development (Mono has been there for some time now for desktop stuff, but I don't know how much traction it got. I don't think many people used it for back end work).
I think the language is really well-designed. It does have a lot of features, but still feels pretty coherent and not overwhelming. LINQ is great. As for what's coming, I'm particularly excited about the non-nullable types in C# 8.0.
I wish it would get low syntactic overhead sum types, similar to Haskell, OCaml and F#. That's the biggest thing I currently miss.
To be fair, in C# a function can "opt out" of async-await with Task<T>.Wait()/.Result/.GetAwaiter().
In a way C# will use a mixture of green-ish threads/threads already, in that await-ed calls are either scheduled on a thread worker pool (via a TaskScheduler) or executed synchronously ("inline")... Which comes with it's own set of surprises and gotchas.
async Task<bool> DoSomethingElse() {
// [0] do something long-running
}
async Task DoSomething() {
var otherTask = DoSomethingElse();
// [1] do something long-running
var other = await otherTask;
if (other) {
// do yet another thing
}
}
So, when will [1] run? Before [0], concurrently on another pool thread to [0], or after [0]? The answer is: you cannot really know from the information presented. The compiler might decide that DoSomethingElse is to be called synchronously ("inline", attached child tasks), so before [1] will get a chance to run. Or it might decide to run it concurrently, but then the TaskScheduler might decide it's doing enough of concurrent work already (e.g. every thread in the pool is busy) and run [1] before [0].
This is usually nothing to be concerned about, until it is. Coming from js' world of async-await where a certain order is guaranteed, I footgunned myself in C#... my real-world DoSomethingElse() essentially was a forever-loop that would only terminate on a CancelationToken (basically a "is this canceled" flag) and the compiler decided it should be executed synchronously for me, so [1] never got a chance to run. The fix was Task.Run(DoSomethingElse) btw, thus explicitly not "inline"-ing the call.
I've been using C# off and on since about 2006 or so. Very early on I was a bit dismayed at how hostile Linux users were to the language. Since it has the potential to fill a large gap in the language development space. Most other langues required knowing a bunch of stuff in order to develop, build, and especially allow naive uses to deploy. The various ecosystems had annoying and often perplexing gotchas. With C# all of those were trivial, especially the last one. (Instructions that start with 'download language version x' would be a non starter)
Excellent article! I hadn't read that in a while and it was a good refresher. I would also prefer going the way of green threads instead. As for typing, I'm coming from C and Python, so the type system has been a fantastic learning experience.
C# is a fine language and it has had traction off the Microsoft platform for a long time.
For instance, many games for the PS(3|4| Vita) are written with something called the PhyreEngine which is based on .NET and lets you make pro-quality games that are portable across those platforms, the PC, and some other platforms too.
C# is my new python: batteries included + Nuget, but faster and properly typed with LINQ sugar on top. What is missing is a great http library, tho the batteries-included stuff usually is enough although a bit clunky.
I’ve made sort of the opposite journey. I’ve worked with C# for a decade, but because IoT and ML has exploded around me I’ve picked up python and now use it more and more.
I really like .Net Core, but as with everything, the more you use it, the better you get at it and I must admit that my C# skills have suffered a tiny bit.
Technically C# is unquestionably better, but there is just something to be said about a single general purpose language, and as far as the efficiency and speed goes, Python is fast enough for our usage.
It's becoming that for me as well. I have yet to run into any real downsides. I'm sure I will eventually hit a few packages that aren't in nuget. But it hasn't happened yet.
Played with yes. And it makes things less clunky, indeed. But it's still built on top of System.Net.HttpWebRequest, meaning it inherits its limitations too, like e.g. sub-par http(s)-only proxy support.
I've been deploying production .NET apps on Linux in Mono and NetCore for a few years now- Core is vastly superior to Framework even if you're not targeting Linux.
We target netcoreapp2.2 and execute the binary by using the dotnet tool pre-installed in containers but you can also just output a binary that can be executed standalone in your chosen platform.
I was able to set up a build agent for CI in a couple of hours; you really only need the SDK and you don't need to go through painful guesswork about what you need to install or copying targets that only exist in the desktop version of Visual Studio or stuff like that.
Also, you don't need to tangle with various runtimes and their licenses (like Java) because there is only one and Microsoft seem to only be interested in monetising their development tools, operating systems and cloud offerings.
I would not have believed you if you told me 5 years ago that C# development could be this good. I could not possibly imagine targeting another language (with the possible exception of front-end code and perhaps front-end web apps)
I think the language is really well-designed. It does have a lot of features, but still feels pretty coherent and not overwhelming. LINQ is great. As for what's coming, I'm particularly excited about the non-nullable types in C# 8.0.
I wish it would get low syntactic overhead sum types, similar to Haskell, OCaml and F#. That's the biggest thing I currently miss.
One thing I am disappointed in is going with async/await paradigm instead of supporting green threads. This essay explains why pretty well, and has already been linked on HN a few times: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...