I like to follow "Modern Microsoft" conventions and styles for C# and dotnet; these are the conventions typically found in modern Microsoft GitHub repos like .NET, EF, etc. They are generally also the defaults within Visual Studio.
I go for standard Microsoft conventions as they would be most popular in the community and would generally be more familiar to new developers joining the team.
1. Boolean Evaluations
😀 DO prefer expression operator short-hand syntax.
var success = true;
if (success)
{
// do if true
}
if (!success)
{
// do if not true
}
Why: Consistent with Microsoft’s .NET Framework and makes code simpler, more concise, and easier to read.
😡 DO NOT use long form operator syntax:
var success = true;
if (success == true)
{
// do if true
}
if (success == false)
{
// do if not true
}
2. Abbreviation Casing
😀 DO prefer PascalCase for a abbreviations of any length found within member names:
public DateTime CreatedUtc { get; set; }
public string SqlConnection { get; set; }
😡 DO NOT UPPERCASE abbreviations:
public DateTime CreatedUTC { get; set; }
public string SQLConnection { get; set; }
Why: Consistent with Microsoft’s .NET Framework and easier to read.
3. Conditional and Loop Brackets
😀 DO always include brackets around single-line conditional and loop statements:
if (true)
{
DoSomething():
}
😡 DO NOT omit brackets:
if (true)
DoSomething();
Why: It makes the scope of the statements clearer and avoids future issues if those statements are expanded.
4. Var Keyword
😀 DO always prefer using the var keyword instead of the
explicit type:
var option = new CookieOptions();
😡 DO NOT use the explicit type:
CookieOptions option = new CookieOptions();
Why: It simplifies the code and isn’t any less understandable.
5. LINQ Single vs Where
😀 DO always prefer using the Where function instead of the Single :
var order = await DbContext.Orders
.Where(x => x.Id == id)
.Where(x => x.Status == OrderStatus.Created)
.Where(x => x.Customer.Id == customerId)
.SingleAsync(cancellationToken);
😡 DO NOT use the explicit type:
var order = await DbContext.Orders
.SingleAsync(x => x.Id == id && x.Status == OrderStatus.Created && x.Status == OrderStatus.Created, cancellationToken);
Why: It improves readability of the code.
Thank you for reading!
If you enjoyed this post and want to stay updated, follow me on Twitter for the latest updates and check out my projects on GitHub.
May the code be with you!
Top comments (22)
Nice!
Just a few complementary points:
(1). I do this one too. I only use the long form when dealing with nullable Booleans.
(2). I seem to remember an MS guideline that stated initialisms with two letters are ok, e.g.
IOException
, vsIoException
.(4). With newer .NET versions, it's also possible to do:
I couldn’t get used with the new() way of declaring stuff. I still prefer var keyword :)
I know what you mean. I mostly use
var
to declare values returned from methods as variables. And so for consistency, I also prefervar
tonew()
.The important is that both are valid, both have no performance implications and both serve to improve readability to different people with different preferences.
@ant_f_dev these are good points. As for the 4th I tend to use
new()
almost always when initiating class property that requires a default object instance.For example:
private readonly Dictionary<string, string> _customHeaders = new();
taken from my
APIClient
used for integration testing where I need to set some custom headers.Ah yes - good call. That makes sense too, as it's not possible to use
var
at the class level.I cannot understand the preference for !success. It is too easy to miss the exclamation mark. Usually randomly is preferred to being concise but most senior developers
To be clear I’m aware that I’m in the minority with this one
To me it was never an issue but again this is a personal preference and so everyone should use what they feel is more readable to them.
I’m the same as you. Then I ran a poll in the office and everyone else prefers the shorter form :(
Yep, different people different preference. However, I can tell you that I have very little code or almost none that checks for false like this
!success
. I tend to always revert the statement, so let's say avoid
method would quit immediately or continue execution.So instead of this:
I would write:
I mostly agree with your guidelines although:
Well if fetching collection that large becomes a problem using LINQ, most likely the feature is not well designed or something else should be used like Dapper.
In 99% of the cases it has insignificant performance impact as multiple
Where
conditions are combined together so there is a single interattion for all. The compiler will be able to cope with it.Here is a reference the LINQ source code of
Where
method:referencesource.microsoft.com/#Sys...
Oh and that 99% of cases apply to in memory collections only. In my example I'm querying from database which has absolutely no difference as LINQ builds an expression tree.
Right, I had overlooked the fact this wasn't linq to objects. I agree that for simple code as in your example, my way of doing things wouldn't be noticeably quicker. However, recently I had to rewrite a huge pile of dung linq to objects for performance reason. The main culprit was some group by and a select many (if I remember correctly) deeply nested on layers of looping over dictionaries... Then I still think that in such a degenerate case, getting rid of a few method calls and object instantiations in the inner most part can be worth it.
Now if I'm being honest, I guess I simply prefer terseness...
I firmly maintain var is a needless abomination and
Gives you all the alleged benefits with none of the ambiguity or inconsistency.
CookieOptions option = new(); is much better than either of the examples. Var makes the code much less readable in situations (myriad) where the object is not immediately created via a direct right hand side construction. It is a very JavaScripty way of doing things, and over any middle-size codebase and above this pattern is deeply harmful for readability. Apart from the single line if thing, most of the rest seem trivial matters of preference but the var one is an actively damaging dogma that seems to have resulted from a poorly thought-through default linter setting in VS and the inevitable bandwagon it inspired.
If I read this list at work I would think that the person who wrote it clearly wasn't ready for dev lead.
Well
CookieOptions option = new();
is almost the same asvar option = new CookieOptions();
the type is just on a different side. Some like it on one side some like it on another. Again it's a matter of personal taste.In the example I used the type of the variable is obvious from the right side of the assignment. It makes it shorter and more readable, requires less typing.
I think you went over philosophical with JavaScript analogy. It is absolutely fantastical that C# evolves in the way that actually let's you choose your style and what is more readable to you or the majority of the team.
It certainly has evolved a lot since its inception. I look at some of the older projects I have and they look so verbose and rigid.
Var is especially useful when the right side is a function call: Said function return value can be changed to another type without needing changes at the call sites provided the new and old types are compatible; and if they're not, unlike with javascript, the compiler will complain.
It's invaluable when refactoring huge codebases!
Many languages have gone the 'var' or 'auto' or whatever way of declaring variables without sacrificing strong typing. And I strongly believe that when reading code, one needs to understand the meaning of variables (hence properly naming identifiers is a must), not their exact type. Then when editing, any IDE will straightforwardly provide you with the exact type...
You nailed it! Especially with this bit:
Of course you need to understand the meaning of the variables: because every piece of code you will read is well structured and properly compartmentalised you will never find clearly delineated type information useful to quickly understand the intended functionality. Said code will of course always be fully commented with absolutely non-arcane variable names and no weird inheritance patterns or etc etc etc...
Of course var can be useful when you only need a quick and dirty refactoring but you know, if you don't understand how to refactor the code such that you retain the left-hand type information without causing compiler issues then I strongly believe you need to understand the variables you are using better (some edge cases with anonymous types accepted)...
If you have to deal with such a code base, you should glorify the team leader, the PR process and the well established coding guidelines of the company. In such cases lack of type would be very worrying indeed.
When refactoring the code the IDE is smart enough these days to avoid such issues and even show you variable type if you really want to. In fact IDE such as JetBrains Rider has this feature called "Inlay Hints" that you can turn on/off whenever you like and shows you the type next to the
var
.Again, you will rarely find this an issue when your code has a decent structure and it is broken into small self contained pieces.