4 ms·
I’m perhaps in a similar camp, years of experience during the .NET 4 era, a lot of TypeScript and Rust after that. Recently, I went back to C# for a smaller pr
by codeflo 4y ago
I’m perhaps in a similar camp, years of experience during the .NET 4 era, a lot of TypeScript and Rust after that.
Recently, I went back to C# for a smaller project. The .NET ecosystem certainly has its advantages compared to the “wild west” of NPM, which includes Visual Studio/JetBrains Rider.
My main problem was that the language feels so dated at this point. Why can’t I make local variables immutable? Why are there still no algebraic types? Why do the new nullability rules feel so inconsistent and tacked on, with “String?” and “DateTime?” behaving completely differently?
I realize not everybody cares about these “modern” features as much as I do, but once you’ve wired your brain to think about program composition in a way that simply feels better to you, it’s very frustrating to go “back”.
.
Edit: It’s not like the C# team is unaware of or in any way against these proposals. There just seems to be little visible progress:
Algebraic types: https://github.com/dotnet/csharplang/issues/113 https://github.com/dotnet/csharplang/issues/113
Const locals: https://github.com/dotnet/csharplang/issues/188 https://github.com/dotnet/csharplang/issues/188
- tester756 4y ago>Why can’t I make local variables immutable? How it'd work in such a case: You declare immutable variable "a" which's an instance of a class and then you execute "DoSomething" method which mutates under the hood? Compilation error? runtime error? Anyway have you tried records?
- codeflo 4y agoI’d be fine with semantics similar to readonly fields (and incidentally, “const” in JavaScript): you can’t reassign the variable, but the contained object can do what it wants. To your last question: Yes, records are really nice syntactic sugar for classes that want to behave like values.
- awild 4y agoIt's usually on a syntactical level, to disable reassigning a value. For objects this means the reference is still mutable, value types are locked. Js has const, C has const, Java final. Imho it'd be awesome if mutability were not the default and we would have to mark mutability, but until then any variable that doesn't need it, is final. Which also helps skimming code
- tester756 4y ago>Js has const, C has const, Java final. C# has readonly and const >Imho it'd be awesome if mutability were not the default If they decided one day that - "let's make immutable by default", then it'd be performance hit - wouldn't it?
- awild 4y ago> If they decided one day that - "let's make immutable by default", then it'd be performance hit - wouldn't it? Not really. It's just a syntactic default, reassigning local variables should be discouraged from except for iterators etc. It just fosters bad habits. For example, A list can still be mutated like usual, the reference however may not change. This usually allows compilers to do optimizations in multithreaded situations. But that's not why I code that way, it reduces the cognitive burden of keeping track which variables are actual moving parts as opposed to context/names etc. > C# has readonly and const Haven't written C# in a few years, GP was talking about variables as far as I can tell and their lack of immutability.
- kroltan 4y agoC# does not (as far as I know) have readonly or const for local variables, only to fields. You can even have consts inside method bodies, but they are only actual compile-time constants. codeflo means to declare a local variable that cannot be reassigned later. void Foo() { // this is possible in C# today, but only for compile-time constants const int Bar = 42; // this is what codeflo wants: variables that cannot be changed after declaration, but can hold runtime values readonly string text = $"Blah: {Bar + System.Environment.ProcessorCount}"; // with such a variable, you wouldn't be able to reassign it later: text = "Some other text"; // the line above would be a compile-time error, just like trying to reassign to a readonly field. }
- mdm12 4y agoI am sure you have heard this before, but F# sounds like it would be right up your alley. It has sane defaults (non-nullability, algebraic data types, etc.) while still targeting the CLR, enabling the usage of any normal C#/.NET library to be used within your application. Granted, there's _some_ friction going between C# and F#, but that is a small price to pay (IMO).
- christophilus 4y agoFor me, another gripe is: “Why do I have to manage a csproj file?”
- codeflo 4y agoThat’s one of the things that tangibly improved IMO: they removed the file list, so except still being ugly XML, the csproj is now very comparable to package.json or Cargo.toml.
- philliphaydon 4y agoA lot… A LOT better than package.json… And can be edited without unloading the project first.
- codeflo 4y agoBetter in what sense? Syntax aside, I don’t see a substantial difference in terms of file content. I do see a substantial difference in terms of tool capabilities (like .NET/NuGet’s inability to resolve conflicting diamond dependencies).
- GiorgioG 4y agoAs much as I'm not a fan of the XML based project files, the csproj format is much more flexible/capable than package.json files. For example, you may want to have different versions of a package reference based on some condition. Would it be better w/JSON than XML? I think it's a toss-up.
- oaiey 4y agoFun thing is the current explaination regards readonly locals: https://github.com/dotnet/csharplang/issues/188#issuecomment-1077768460 https://github.com/dotnet/csharplang/issues/188#issuecomment... It is basically: if we introduce it, it gives us a tiny benefit for a gigantic amount of noise during every single code review. It boils down to comparing developer productivity vs. language safety. I find the argument a bit weak since code review guidelines can end this conversation AND C# has already quite some code analysis code fixes to auto-fix language usage stuff (like file scoped namespaces or nullability checks). And that case of const and readonly can be algorithmically checked.
- trinovantes 4y agoIt does seem like a weak argument when it can be enforced/fixed by linters e.g. this is already solved in JS with eslint prefer-const rule I suppose you can emulate it today with variable prefixes/suffixes and check the AST with a custom linter yourself
- awild 4y agoEspecially since its not really a language safety feature. As a reader of code I much prefer knowing what I need to pay much attention and what not. As a writer I want to be reminded when I promised myself to not touch a variable.
- codeflo 4y agoSome of the comments in that thread must come from people who are lucky enough to have never had to read or refactor any large, convoluted methods. Knowing that this particular bool flag isn’t being flipped thrice, 100 lines down, is a godsend.
- oaiey 4y agoThat is indeed a problem every once in a while. These people develop a framework and 3 languages. They do not built large systems. But there are other groups at Microsoft which keep them on track with their real needs.