> Subpar tooling outside of Windows (I'm looking at you C# Dev Kit)
JetBrains Rider is excellent and runs on Windows, Mac and Linux. It has a few Windows only features but nothing important for me, it's the best IDE for C#/.NET you can get on non-Windows platforms imo. And it's free for non commercial use.
I use rider on Mac (and windows to be fair) and i think the experience is better than visual studio on windows.
My biggest gripe with dotnet tooling is dotnet format. It’s not quick enough to use on a pre commit hook, so people don’t run it regularly and we get failures for it.
It’s such a small nit, dotnet is a great environment to work in
Most of the newer features make C# less cumbersome to use. I can't imagine using the language from ten years ago, in fact the first thing I do when working on a legacy app is to set langVersion=latest.
Sometimes less is more. It very easy for devs to use the language in completely different ways. I lean towards Go style in that regard. My ideal language would be like Go + Linq.
I've heard this argument before from the perspective of C# having more keywords and language features to be aware of than something else (in my particular argument, the other side was Java).
From this perspective, I can't say I disagree as such. If you look at the full set of language features, it sure is a lot of stuff to know about. The argument that it is too much, and that we should sacrifice expressiveness and signal to noise ratio in the code to keep the language simpler, I don't agree with.
> * Culturally, it feels like .NET devs are less "passionate" about their work
Only in the "stove pipe industry" as we say here. Mobile gaming is massively C#-based for example and the people are really passionate about what they do.
And for a backend dev, the scale of stuff you get to work with is cool.
Why is EF regarded as such a good ORM? I've encountered countless bugs in different repos related to its stateful nature after many years in .NET. Personally I found it completely illogical for my ORM to maintain state. I just want it to hold my schema and build queries.
Are you referring to the change tracker? FYI you can have it skip tracking as the default (or per query), but when you actually want to make changes you better opt in with `.AsTracking()`.
Anyway, I've used EF at work for about a decade and I'm happy with it. I surely have blind spots since I haven't used other ORMs in that time, but some things I like are:
- Convenient definition of schema.
- Nice handling of migrations.
- LINQ integration
- Decent and improving support for interceptors, type converters and other things to tailor it to our use cases.
What ORM do you prefer, and how does it differ by being stateless? How does saving look like, for example?
Dapper can be a better fit depending on the scenario. It's dumb objects. You fill them yourself with actual SQL statements. There is no change tracker. You are the change tracker.
The main issue with EF is ultimately there is an expression builder that maps linq expressions to sql. This mostly works, until it doesn't, or it does but has strange generated sql and performance. If all you are doing is CRUD or CRUD adjacent then it's fine. But for some complex stuff you spend a lot of time learning the innards of EF, logging generated statements, etc. It is time better spent writing good sql, which something like Dapper allows.
Fair enough. We use Dapper for a handful of performance-critical queries. But I wouldn't want to use it for the 99% where EF works well. Just like I wouldn't want to hand-roll assembly more than where it's really needed.
And it's not just about performance. LINQ plays well with the same static analysis tools as the rest of C#. You know, type checking, refactoring & co.
EF hits you in the face right at the start with the massive convenience that it provides. And then the paper cuts start adding up, and adding up, and adding up.
Although the EF team has made huge progress towards keeping your entities persistence-unaware, it's still not enough and eventually you wind up building your project in Entity Framework just as much as in C#.
Being forced to compromise your domain model. Yes the product has improved this greatly in recent years but it’s still inadequate IMO.
Fluent syntax can at first seem like the product has achieved persistence ignorance nirvana but then you have to compromise a little here, compromise a little there, until some point, if you’re still thinking critically about the design, you realize that you’re writing your app in Entity Framework as much as you are writing it in C#, as I mentioned.
Passing around a large mutable blob (dbcontext) which, if not managed with the utmost discipline by your dev team, can make it necessary to understand what large swaths of the code do before you can adequately understand what any small part of the code does.
I don't think C# really has bloat — there is generally very little overlap between things they add, and each release they don't add a lot. This release's big thing was better extension method syntax and the ability to use "field" in properties. Each release is about that big, and I feel like the language is largely very easy to internalize and work in.
New features are often more likely to be semantic sugar instead of some new big thing.
It’s funny, I came up in my career working in places mixed with .NET and PHP/JavaScript devs and the .NET developers all felt the PHP/JS teams were clown cars.
IMO had .NET Core come out a few years earlier it would have a much bigger marketshare today, but when you had Ruby/PHP/Node/Python devs primarily using Macs, no one wanted to touch the thing.
Could not agree more. Too many -- WAY too many -- "features" from Javascript and functional languages have been jammed into C#, and the language has suffered for it. Every time I see "var blah" in C# code I cringe at how lazy you must be to not use strong typing when declaring a variable.
Same goes for "astink / await". If you need asynchronous multi-threaded code, use the damned Thread Parallel Libraries that Microsoft provided over a decade ago. Being forced to have every damned thing you write in C# wrapped with astink is just one giant code smell.
Yes, I'm old. Thank ghod I'll be retiring very soon, because as far as I'm concerned the tooling and languages I've used over the past 50 years have taken one step forward and at least three steps back in the past five years...
If you take it in the context of the industry, I think async/await is the more imperative friendly option. It let's you write code sequentially without callbacks. And the performance gains are definitely worth it. I'll have to respectfully disagree
If the deal is in California's and OpenAI's interests roughly than there is no corruption. Sure they're using their big weapons but there's not a major principal-agent divergence on either side from what I can see. Altman wants to build the business (and make money) and California wants the tax revenue and maximize chances of the core business remaining largely in the state.
I've found it quite annoying, I'm considering going the other way for my personal project from Go+Templ+HTMX -> Flask + Jinja + HTMX. Still undecided though.
I feel like Go is quite verbose and defining templates in Templ feels painful.
I made the switch from FastAPI + Jinja + HTMX to Go and embedding the HTML into the Go binary directly... it's very nice being able to run the apps without an interpreter. I'm able to make ~5MB sized containers to run the full stack
there's a performance increase too, but these apps I'm talking about are so simple it's not enough to really notice. objectively FastAPI is really good and makes running a simple site so easy, I'd still recommend to most people using that.
I'd say the family resemblance is the other way around. F# was influenced by Haskell, both in syntax and semantics. Just as Haskell was influenced by early ML.
Haskell and ML make up one of the major language families. They are more like each other than they are like other languages. Inspired by the lambda calculus. Strong static typing with type inference. A succinct math-like syntax that emphasizes pattern matching.
Haskell goes further with syntactic sugar and tries to be almost equation-like:
a = 5
f = \x -> x + 1
g x = x + 2
f $ g a
SML:
val a = 5
val f = fn x => x + 1
fun g x = x + 2
f (g a)
But F# like Haskell makes no distinction between values and functions:
let a = 5
let f = fun x -> x + 1
let g x = x + 2
f (g a)
The use of indent-based blocks is another Haskell-ish influence on F#. But now we're awfully close to bikeshedding.