β Commandments for C# developers?
Came across this cool article
http://www.lysator.liu.se/c/ten-commandments.html
I was thinking what according to you should be the commandments for C# π
69 Replies
- Don't use
Convert.To*
- Prefer System.Text.Json over Newtonsoft.Json
- Enable nullable reference types
- Use the latest full release or at least LTS
- When in doubt, refer to the official Microsoft documentation
- Use the dotnet
command and nothing else
- Write unit tests when applicable
- Follow the standard conventions (with minor acceptable deviations)
- Prefer composition and interfaces over inheritance
- Don't use "pure" OOP, good and efficient code is usually a combination of functional, object-oriented, and imperative
The first two are kinda specific and you could probably replace them with something more generalNewton soft is so much faster, and just better, why not use it?
And what about msbuild
STJ is way faster
And afaik STJ can do everything that Newtonsoft.Json can
dotnet
just runs MSBuild, there's no reason to invoke MSBuild manuallyI'm too used to Newtonsoft to switch π¦
But I really should
STJ is optimized to hell
I feel like some form of "Google before you ask" and "Don't rely on AI generated code to help you" are pretty good commandments to add to it
Probably "Learn LINQ"
Or you could use smth else than json, like xml or smth
I think I'm more than happy with json, thank you
i just wish there was a cson serializer π
But can it parse json into expandoobject??
I don't think you can and I don't think any sane person will think that's a bad thing
STJ misses some features but they are pretty specific
And most have a workaround which is described in the migration
I wonder if STJ could be sped up even more with source gen like GeneratedRegex
Getting rid of the need for reflection likely did.
How'd they do that
Oh wait am I just imagining that they made an SG for STJ?
No, they did
Since it uses a source generator, it can inspect the class it's meant to deserialize to at compile-time and generate specialized generation logic for that class
-
await
the async
s
- don't use dynamic
- do NOT use dynamic
- avoid object
- if it's deprecated, it's probably for a good reasonthose are some commandments i trust
for 6 years straight
Pretty sure STJ has the ability to create source generated code for you as of .NET 7
I just got another commandment from another thread:
- Do not use Region directives, ever
- If something seems too difficult, you're probably doing it wrong - or it's the wrong thing to do
- If you fix a bug, add a test
- If you can't come up with a descriptive name, it needs to do less
- Reuse only applies to logic, not code; don't be afraid of models. They aren't hurting anyone over in that folder
- Don't fix the bug, fix the cause of the bug
- If there isn't a library that already does it, it's probably a bad idea
- Assume your code will never be reused. Don't get fancy making it all generic and complicated unless that's part of the design
Unknown Userβ’2y ago
Message Not Public
Sign In & Join Server To View
I feel that one. One of my co-workers thinks it's important to encapsulate sections of a function in regions I'd add
"Never recreate HttpClients. Use one shared instance or (if using ASP.NET) inject IHttpClientFactory" to the list
I mean, its only purpose is to hide the problem
I agree with everything!
6 years straight
- If there isn't a library that already does it, it's probably a bad ideaehhh, this doesn't take into account if you're doing something very esoteric which actively requires a custom solution. I do agree that for most things there are most likely libraries which do that thing way better than you ever could, though.
Unknown Userβ’2y ago
Message Not Public
Sign In & Join Server To View
except when youre too stupid to do it yourself for example, me with d2d, i used unvell.d2dlib for 2 years
Do you mean "descriptive name" for a method,property and classes etc?
But isn't it a good thing to consider "loose coupling"?
Could you also tell why?
Can you elaborate on use dotnet command and nothing else. Are you saying donβt click run inside visual studio? Instead using cmd?
Regions only exist to hide the problems you're supposed to fix
But what if you have a really long class(with really long method definitions)
It helps us to navigate?
I mean it mains as in don't use
csc
or MSBuild directly, using an IDE is obviously fine.What I mean is just that if you think you have some clever idea about how to do a (common) thing, and nobody else has a made a library that already does it... there's probably a fundamental flaw to the idea, or someone would have done it already
Make the methods smaller by splitting them into more methods. Make the class smaller by splitting it into more classes with fewer responsibilities. Repeat until you no longer want regions
Can you elaborate?
You can collapse methods without regions
Sometimes splitting classes into smaller classes is way more annoying than having it all in a single class
It's only a reason to hide big chunks of problematic code
That's not any different from regions really
Collapse multiple methods with regions and it's a nice way to group things
Yes it is different
Have multiple constructors? #region ctors
Regions just give yout he chance to hide it altogether
If you need it, you are hiding a problem
If you don't agree, you most likely never used it or you don't understand my reason
Region is a code smell
I didn't agree with your initial statement that they only exist to hide problems, needing them is different
I love the fact that regions exist but they never hide any issues in my use cases. Makes it very easy to glance through code and find what you need quickly
- Don't use Convert.To*
System.Convert.ToBase64String
though They always hide issues
okay that's an exception
If they don't you probably don't need them at all
I'm using then, works perfectly fine for me
Never had a reason to
It's not gonna pass any review where I'm working
Well where you work isn't where everybody works either so...
I don't have to pass reviews
My point is that Regions are considered a code smell quite often. I just took my work as an example
But feel free to use them
I don't feel like convincing you
Just messing around but I agree with the point
Annoying is OK, making any given set of logic more readable and maintainable is usually more important. Within reason. And a lot of that annoyingness comes down to how the project's folders are setup; if you're splitting some class into 5 others, make a folder and put them all in it because they're clearly all closely related
Mostly I'm referring to [Thing]Manager classes, which seem to show up everywhere and people seem to think it's OK to have one class whose responsibilities are to manage everything related to [Thing]
But of course somewhere along the way, it became the norm to organize things by what they are, such as an interface or model, instead of by what they do or relate to. They don't let me, but I'd love to put my DTOs in my interfaces (preferably as records), and/or put implementations in the same folder as its interface, which all goes in a folder relating to the feature
- If you use .Result or .Wait() on a Task, you're going straight to jail
- Use Task.WhenAll to await multiple tasks
- Use DI when possible
- Don't optimize something before you even know it's an issue
- Respect nullability
- Use the right tools for the job instead of just repeating what you are familiar with
- Respect SRP and DRY
At least these are the ones I come up with on the spot
- Always test your code by running it locally
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.Wait, why not? Because I think I used it. π
$tryparse
The TryParse pattern is considered best practice of parsing data from a string:
- a TryParse method returns
true
or false
to inform you if it succeeded or not, so you can use it directly in a condition,
- since C# 7 you can declare a variable that will be used as an out
argument inline in an argument list,
- it forces you to check if the out
argument contains valid data afterwards,
Avoid: Convert.ToInt32 β it's a bad choice for parsing an int
. It exists only for backwards compatibility reasons and should be considered last resort. (Note: Convert does contain useful conversion methods: To/FromBase64String
, To/FromHexString
, ToString(X value, int toBase)
, ToX(string? value, int fromBase)
)
Avoid: int.Parse β you have to use a try
/catch
statement to handle invalid input, which is a less clean solution.
Use int.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=net-5.0#System_Int32_TryParse_System_String_System_Int32__ Int32.TryParse Method (System)
Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded.
umm, if not used responsibly, what issues do they cause?
But they say it is an exception(means we can use it? Or was it a joke?)
System.Convert.ToBase64String
is the exception to the ruleyes xD
This is one of the
Convert.
methods that can be used freely
But Convert.ToInt32()
and their ilk, shouldn'tConvert
class is great. its especially useful when dealing with code from c++ in certain casesDon't do sync over async unless you 200% sure that you own and control thread in which you do it
Eh,
int.Parse
should be avoided when parsing user input, as an exception can be avoided. There's no problem with using it with anything else though, so this is kind of misleading
If I parse data that I expect to be an int I see no point in creating a whole tryParse statementnot everything, last time I tried I couldn't cast properties into an object
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.