The coding conventions I use for C# and why I use them

preview_player
Показать описание

Hello everybody I'm Nick and in this video I wanna talk about the coding conventions I use when I'm writing C#. This is a heavily subjective and opinionated topic, so the conventions themselves don't matter. What matters, no matter the convention, is the story behind it.

Timestamps
Intro - 0:00
Top level folders and projects - 1:13
Unit test naming - 2:12
Folder naming - 3:05
Class naming and conventions - 5:20
Var vs explicit type - 7:04
Class ordering - 9:00
General stuff - 11:21

Don't forget to comment, like and subscribe :)

Social Media:

#dotnet #csharp
Рекомендации по теме
Комментарии
Автор

m_ stands for member (as in "class member") from the days of Hungarian notation and intensive C++.

PedroPabloCalvoMorcillo
Автор

I also always use

var persons = new List<Person>();

instead of

List<Person> persons = new List<Person>();

But since C#9 I've switched to

List<Person> persons = new();

Nice and short, just like var, but still the type is clear.
Everybody wins.

RonaldZaZ
Автор

Enum names should be singular when their intent is to be used as a singular value (i.e. ConsoleColor), but should be pluralised when their intent is to be used as multiple values (i.e. BindingFlags)

MrMatthewLayton
Автор

I love the way you explain things straight to the point. Very easy to follow.

RDWize
Автор

Didn't know an "implicit operator" was a thing. But then again, I didn't know lots of things were a thing until I watched your videos.

Regarding the var type. The official C# conventions from Microsoft state that if you can't tell what the type is from the right side of the assignment, then you should use the explicit type.

georgeti
Автор

Pretty much matches what I use. Only thing I do a bit different is where I put private methods. I put them close to the methods they're called from if possible. My biggest issue I run into is coming up with good folders / namespaces for classes that don't really fit into any specific thing.

JackLyons
Автор

a video about formatting, for example long linq statements would be awesome

Daveduddle
Автор

m_ means member_, so basically exactly what you mean, but now that stuff can start with _ instead of needing to start with a letter it's shortened to that.

DarthJane
Автор

I always wondered why so many people put properties *after* constructors. I mean, they are most often treated like ordinary fields (especially when using auto properties). Heck, they can even be set directly from the constructor. In such case it is 100% reasonable to put them *before* the constructors, but *after* the fields.

Why?

promant
Автор

I agree with just about everything you said here (and we use them with our project at work) except for "var". I personally hate the use of var for just about anything except when returning anonymous objects from a LINQ query. We spend so much time with standards for variable and method names so developers can easily tell what something is, but for some reason when it comes to declaring variables we are ok with making it generic and having to do something to see what it is. But.... that's just me. And other members on my team do not agree, so we don't have any standard around it's use. But as always, great video!

brianm
Автор

I always prefer using *this.* instead of *_* for the reason that they are easier to spot and select.
Another reason is that *_* feels like an old custom and the code looks more messy.
I took time to decide which one to stick to, and I went for *this.*

paulwhiterabbit
Автор

When you work in a team or corporate environment, there is usually a business wide defined coding standard to follow, but it's always good to establish your own good clear practices even when working on your own code. You never know when you may have to dust it off and update/debug it and it gets you into the right habits from an early stage. On some platforms, coding standards become a natural extension of the syntax, i.e. user defined types, naming conventions, etc. I know your (Nick) applications are primarily .NET and webservices, but its well worth any coder looking at what standards already exist (and are expected by those communities) before implementing their own. All of which is better than just having no standard at all! Another great video Nick.

simonbaxter
Автор

I tend to agree with using var where possible. I program more Rust than C# at my job, but the same trade-offs seem to apply to both. FYI, Rust variable declarations go like this:
let userId: Guid = ...; // explicit
let userId = ...; // implicit
In Rust and C# 9.0 there are also target-typed value expressions, for example:
List<uint> nrs = new(); // C#
let nrs: Vec<u32> = empty().collect(); // Rust
(This is not the normal way to create an empty Vec<u32>, just an example of target-typing (because new is not a keyword in Rust). "vec!()" or "Vec::new()" are the normal ways. But collecting the empty iterator works for many types, "let map: HashMap<u32, u32> = empty().collect();" is another example.)

The question that I struggle with is this:
If I have to choose between a target-typed place-expression or a target-typed value-expression, what should I do, any why?
I have not been consistent with this, and cannot decide on a preference either. Often I suspect that the ambiguity will go away when I refactor later that day, but it would be nice to have a guideline to follow.
(I think that C# might use the name "L-Value" for place-expressions and "R-Value" for value-expressions, like C and C++ do. I'm not sure what terms C#-programmers are more familiar with.)

The C# example of my question would be this:
var foobar = new(); // ambiguous
var foobar = new T(); // option one
T foobar = new(); // option two

upgradeplans
Автор

I think a lot of crutches went away when something about code design clicked for me. I stopped using underscore on fields a long time ago and never regretted it. Similar to var, I seldom care and my IDE shows it easily. Also I never had a bug from var everywhere. Or from not including the default "private".

SecondFinale
Автор

When I am naming things, (serializing JSON into a model in c#) resharper hates the naming because it isn't Pascal. The name is usually lowercase because it is coming from a JavaScript style object. My model classes always have to use the ignore naming comments for resharper.

chefbennyj
Автор

Regarding the Async suffix. If the methods in a class are mainly async i don't use the Async suffix but put the Sync suffix on those methods that are not asynchronous.

Gargo
Автор

Great material as always. Even though I already follow and mentor most of the practices you use, I still watch your videos to learn something new or challenge my thinking.

One change I would suggest is to the service layer. I'm always uncomfortable seeing the service layer in the same project as other layers. I much prefer a separate project for each service. It finally clicked for me why that is...

When you combine services into a single project, or combine in a project that is not a service layer, you run the risk of code leakage. A developer will eventually create a class that supports multiple services which starts to bind the services together in what initially is innocuous but slowly evolves into something more difficult to disentangle. Separate projects allows the framework to guarantee the absolute separatation of concern that ultimately leads to cleaner more supportable code.

Projects can be viewed as nothing more than folders which enforce isolation. Anytime our architecture dictate a separate area of concern, that area should be a separate project with clear interfaces and boundaries.

gregpetrites
Автор

You should do a video on your visual studio setup, theme, tabs and all the extensions you use in it.

atro
Автор

Little more from my perspective of exceptional cases in using var everywhere I can. Dealing with explicit operators is very rare scenario for me. Mostly I specify type when introduce some uninitialized, or initialized with null nullable variable (class or nullable value) out of some scope where it can be initialized or must be initialized in some conditional way. Another often scenario is when I want to generalize returned by method class to base class or interface.

iGexogen
Автор

What kind of IDE Software that you use in this Video?

inzaghip.a.