I’m also still mad at them for competing against amazing stuff like ServiceStack (a real OSS project from the community, and the best way to run REST APIs I’ve ever seen) with “official” but worse stuff like ASP.NET Web API. They do this a lot, some OSS gets popular but instead of embracing it, they make a half-assed ripoff, proudly proclaim it “official” on conferences and all the C# devs jump off the cliff like lemmings, and the original OSS project dies/stagnates. MS might have officially embraced Open Source but they’re absolutely awful at fostering an OSS community.
But .NET itself is amazing! There’s this weird misconception in Microsoft land that if you choose .NET you must also use all MS’s half-assed libraries. Just use Postgres! Use a lean ORM like Dapper, use Redis, use whatever you want from the wider OSS ecosystem. There’s nothing about C# that forces you onto Entity Framework. Get out of that red polo shirt and look around, there’s a lot of cool stuff out there.
That said, ServiceStack has transitioned to payware a long, long time ago and I'm pretty sure that is what's caused its demise, not ASP.NET Web API. As a single anecdotal data point, it's definitely the reason I'm not using it.
still have yet to learn / try dapper
I have had two projects where the customer paid to rewrite their .NET Framework applications into Java, instead of the more sensible idea to migrate to .NET Core, as they saw it was more valuable to them to move completely away from Microsoft stack.
> There’s this weird misconception in Microsoft land that if you choose .NET you must also use all MS’s half-assed libraries.
The way I see it, it's more the opposite really. People chose .NET (or more specifically C#), because, they want to use it's tooling and if you're not going to use it, then why would you pick C#? .NET on it's own is excellent, I'm not sure if I think it's as good as the JVM, but it's definitely gotten very good in the recent years, but why would you pick it if you didn't plan on using the "official" tooling?
I'm sure there are some good answers to that question. We just haven't found any.
Because it’s a great language with amazing tooling. It’s fast, robust, easy to debug, easy to refactor, and so on.
It’s also very easy to learn for novices and experienced programmers alike because it’s kind of the middle ground between many popular programming paradigms, and it has few surprising gotchas. It’s a fast way to get a heterogeneous team productive.
I agree but I also think the main issue with this is that you could've said it in reference to most programming languages in 2023. I'm sure people can have a lot of debate on that, but aside from the fast bit, most programming languages are frankly in excellent places today, and fast is sort of irrelevant for us specifically as we tend to use c/c++ for that.
Compile errors are super long lines and don’t show an excerpt of the code with underline under what went wrong with suggestions on how to fix it?
I know I’m asking a lot here, but that level is available with Rust and Elm.
What do you mean by this?
You do get the same information in the IDE from intellisense.
When order of declaration matters, it ceases to be declarative. “Let there be a function” is instead “make me a function”.
It’s entirely unnecessary, and even JavaScript can let you run a function that gets declared later.
The advantage when order does not matter inside the module is that you can list big things at the top of the file and the smaller things it’s made of below, rather than opposite.
The advantage when order does not matter outside the module system is that you can have mutually recursive modules.
I didn't particularly mind the new way project files are made up in .NET. It used to be a lot worse too. But at the same time, it can be cumbersome as you point out here and for whatever reason, it's these small annoyances that so rarely get fixed by Microsoft allowing them to pile up. I mean, I just said it used to be worse, and it really did, but then when they made it better they didn't make it great. Which is something I'll just never understand, especially because they did it recently, so it's not like they couldn't have taken inspiration from other languages and done it right.
That’s literally it: they couldn’t.
It’s hard to duplicate good effort and make it profitable. So many people make either valuable or well-made things.
Explain? This isn't an assembly line, it's not a question of scaling handmade artisanship.
But yes .. when you step out of the well-defined area in .net you have an "Apple moment" where trying to do something they didn't anticipate or actively dislike becomes wildly, unreasonably difficult and you get pushed down a hacking rabbithole. I'm quite proficient at MSBuild now but I shouldn't have to be.
It's also part of the ocaml legacy (I believe file order matters in ocaml as well).
Just as a counterpoint to this, I have found Entity Framework (Core) to be an extremely nice and very productive dev experience, with a lot of constant improvements in every release. MS don't always get it right, but I definitely wouldn't call EF a "half-assed, badly run project" by a long stretch. (Though there are probably other MS projects I might be more inclined to describe as such!)
That said, they were pretty brutal in cutting off legacy support for those still using .NET Framework and trying to migrate. Through luck, I didn't have to suffer too much pain, but the migration story from .NET Framework to the new world of .NET (including EF to EF Core) has not been the smoothest for some scenarios.
If you're still using .NET Framework at this point, that's your own fault (or, more likely, your org's). They have been communicating for _YEARS_ that .NET Framework was on its way out, and provided support for .NET Standard 2.0 as a stepping stone to .NET Core & beyond (i.e. .NET 5+). There are some apps & frameworks that don't really have a modern .NET equivalent, but you won't find me shedding any tears over the lack of a direct upgrade path for Windows Communication Foundation (WCF). =P
That means Microsoft strives to provide a first-party library for every business case.
That said, you can still use ServiceStack and Newtonsoft.JSON if you wish to.
Compared to my projects that (begrudgingly) use Node.js...
We’re switching to Go for concurrency. C and C++ for computation (though to be fair, we were already doing this with C# and the integration between them has always been great).
Our generalist language has become TypeScript however. Not because it’s great technically, but because it lets us share resources better which in term has made us much more productive in meeting our business needs.
I don’t think C# is bad, I also think it’s much better today than it used to be. If your use of it remains within what works well I think it’ll be hard to find a language with better tooling, but if your needs go beyond that you’re going to have to fight it a lot.
Nothing. This often happens when people don’t know .net to begin with. Better they go to go than complain about non existent issues in. .net.
// The tasks will run in parallel
var data = service.GetData(id);
var user = service.GetUser(name);
Handle(await data, await user);
Re: the above comment on switching to Go for concurrency - probably one of the most ill-informed things I have read in the last few days. Doing this borders on incompetence due to the lack of analysis of the utilized technology - Go's GC offers far worse throughput and its concurrency story at best is "on par" with C#.The simplicity of this approach and the advantages this brings to code structuring and easy refactoring simply cannot be understated.
Task-returning method indicates an asynchronously produced (deferred/delayed) result, a promise. If a language hides this fact (that the returned value needs to be awaited), it is grossly misdesigned - at most it can offer not blocking a thread, completely missing the point and leaving 20 years of improvements other programming languages have on the table.
But it's not as bad, yet instead in many other languages you are forced to manually schedule and then block/join until all of your tasks/promises/goroutines finish. Not in C#, that makes it as easy as it gets, which you can see in my example.
On top of that, you always pay for concurrency in Go, even when you don't use it, it is by definition always "colored" which further contributes to the overhead.
Also, in my example, the tasks will run in parallel. They won't in Go.
Very hard disagree. This depends on your computing philosophy. Go was designed based on the principles of CSP in mind and that code is produced by humans for humans first. The CSP architecture has proven to work and fit well for high-concurrent middleware.
You are not forced to block until goroutines finish as you claim. You can do other work or yield to the go scheduler. All the necessary busy work is taken care of by the runtime - which is terrific for folks who don't want to fiddle with low level details.
> On top of that, you always pay for concurrency in Go, even when you don't use it, it is by definition always "colored" which further contributes to the overhead.
And that is a completely fair compromise. Supporting easy concurrency natively in the runtime was an excellent design tradeoff since the computing world is moving to more and more cores. There are fewer and fewer uses for non-concurrent software.
What would the Go code look like that achieves identical behavior to the example above (tasks are dispatched concurrently and executed in parallel)?
As a side note I really don’t think C# does parallelism better than Java.
If two callers call the same method concurrently, whether it requires any synchronization or a more advanced primitive like Channel (for which C# has well-written implementation) or nothing at all is a case-by-case choice.
Java's parallelism by definition cannot be better because they had to retrofit a green threads design onto existing ecosystem, only ever addressing the hardware thread blocking issue with all the ceremony and bloat to do the most basic actions concurrently and/or in parallel still remaining in place.
Java requires far more steps to achieve comparable behavior for what C# requires you doing nothing or a method call at most. Dispatching array elements to a consumer in parallel? call .AsParallel(), and no, Java's Stream API requires more work. Want to fire off two asynchronously completing methods? Just use the example above, neither Java nor Go can hold a candle to this. Methods are CPU-bound and blocking? Easy - just use Task.Run to achieve the same.
I’m sorry, but it’s really not the same thing. You appear very confident, and sort of rude, in your argumentation, but there is just such a huge difference between parallelism and concurrency I don’t even know where to begin. I mean, you’re talking about (a)synchronous calls, tasks, and, what not, but what you need to solve is when two thousand sensors want to update the same data through the same service all at once. And they want to do this fairly often.
In reality it’s even more complex than this because a lot of the sensors carry data on behalf of each other so often you’ll receive the same data multiple times and so on, but there isn’t much need to get into that.
But hey, you do you, if C# works for you, great.
We use it for a range of things. Mostly related to the legacy software of when our developers were mostly C# developers. Which isn’t how things are now, as C# has often stood in the way of our ability to deliver business value at a rapid pace while keeping maintainable systems. Not so much the languages fault as how Microsoft manages a lot of the libraries. Like how the model builder for EF and OData (both official Microsoft libraries) don’t work together and how you need to extend basically any standard library to do any real work with them. So while it’s actually a decent language, if a bit verbose, and .NET is sort of solid these days, we honestly have very few success stories with it.
Some of our AD (now Entra ID I guess) integration operates on it while we slowly migrate it to Powershell (which is .Net but runs in Azure Automation). Some of our APIs run with it. We have a few azure function apps (in containers and isolated) which are being migrated to other techs, and non-function apps. So it’s not like it’s not “working” for us, it’s just that it works a lot less great than its alternatives, even despite a it’s huge leap forward in recent years. Honestly it feels like Microsoft mostly keeps C# around because it sells licenses to medium sized stagnating companies, considering how “half-finished” a lot of the libraries are and how poorly so many of them function together.