C# Cheat Sheet

Jorge Perales Diaz
EnigmaMx
Published in
4 min readApr 18, 2021

--

Writing beautiful, understandable code is just as important as writing a production code. There are many different guides and guidelines on the Internet.

I tried to go through all of them and put together a little cheat sheet. I have included only those rules that affect the style of the code and cover most of the key points.

Hope you find this very useful!

Layout

  • A maximum of one statement per line.
  • A maximum of one assignment per statement.
  • Indentation of 4 spaces, no tabs.
  • Column limit: 120.
  • Line break before opening brace.
  • Line break between closing brace and else.
  • Space after if/ for/ while etc., and after commas.
  • No space after an opening parenthesis or before a closing parenthesis.
  • One space between the operator and each operand of all other operators.
  • Add at least one blank line between method definitions and property definitions.

Comments

  • Place the comment on a separate line, not at the end of a line of code.
  • Insert one space between the comment delimiter (//) and the comment text.

Naming

Do:

  • Names of classes, methods, enumerations, public fields, public properties, namespaces: PascalCase.
  • Names of local variables, parameters: camelCase.
  • Names of private, protected, internal and protected internal fields and properties: _camelCase.
  • Naming convention is unaffected by modifiers such as const, static, readonly, etc.
  • Names of interfaces start with I, e.g. IInterface.
  • Filenames and directory names are PascalCase, e.g. MyFile.cs.
  • Choose easily readable identifier names, e.g. a property named HorizontalAlignment is more English-readable than AlignmentHorizontal.
  • Favor readability over brevity, e.g. a property name CanScrollHorizontally is better than ScrollableX (an obscure reference to the X-axis).
  • Use semantically interesting names rather than language-specific keywords for type names, e.g. GetLength is a better name than GetInt.

Do NOT:

  • Use underscores, hyphens, or any other nonalphanumeric characters.
  • Use Hungarian notation.
  • Use identifiers that conflict with keywords of widely used programming languages.
  • Use abbreviations or contractions as part of identifier names.
  • Use any acronyms that are not widely accepted, and even if they are, only when necessary.

Argument:

  • If the argument is a literal constant, and the same constant is used in multiple function calls in a way that tacitly assumes they’re the same, use a named constant to make that constraint explicit, and to guarantee that it holds.
  • Replace large or complex nested expressions with named variables.
  • Consider using Named Arguments to clarify argument meanings at the call site.

The var keyword

  • Use of var is encouraged if it aids readability by avoiding type names that are noisy, obvious, or unimportant.
  • When the type is obvious — e.g. var apple = new Apple();, or var request = Factory.Create<HttpRequest>();
  • For transient variables that are only passed directly to other methods — e.g. var item = GetItem(); ProcessItem(item);

ref and out

  • Use out for returns that are not also inputs.
  • Place out parameters after all other parameters in the method definition.
  • ref should be used rarely, when mutating an input is necessary.
  • Do NOT use ref as an optimisation for passing structs.
  • Do NOT use ref to pass a modifiable container into a method. ref is only required when the supplied container needs be replaced with an entirely different container instance.
  • Do NOT use ref or out modifiers to overload members.

Use of tuple as a return type

  • In general, prefer a named class type over Tuple<>, particularly when returning complex types.

Default values/null returns for structs

  • Prefer returning a ‘success’ boolean value and a struct out value.

Attributes

  • Name custom attribute classes with the suffix “Attribute.”
  • Attributes should appear on the line above the field, property, or method they are associated with, separated from the member by a newline.
  • Multiple attributes should be separated by newlines. This allows for easier adding and removing of attributes, and ensures each attribute is easy to search for.

Structs and classes:

  • Almost always use a class.
  • Consider struct when the type can be treated like other value types — for example, if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

Class member ordering

Group class members in the following order:

  • Nested classes, enums, delegates and events.
  • Static, const and readonly fields.
  • Fields and properties.
  • Constructors and finalizers.
  • Methods.

Within each group, elements should be in the following order:

  • Public.
  • Internal.
  • Protected internal.
  • Protected.
  • Private.

Property styles

  • For single line read-only properties, prefer expression body properties ( =>) when possible.
  • For everything else, use the older { get; set; } syntax.

Constants

  • Variables and fields that can be made const should always be made const.
  • If const isn’t possible, readonly can be a suitable alternative.

Exceptions

  • Do NOT return error codes.
  • Use the prefix “Try” and Boolean return type for methods implementing this pattern.

String interpolation vs String.Format() vs String.Concat vs operator+

  • In general, use whatever is easiest to read, particularly for logging and assert messages.
  • Be aware that chained operator+ concatenations will be slower and cause significant memory churn.
  • If performance is a concern, StringBuilder will be faster for multiple string concatenations.

LINQ

  • In general, prefer single line LINQ calls and imperative code, rather than long chains of LINQ. Mixing imperative code and heavily chained LINQ is often hard to read.
  • Prefer member extension methods over SQL-style LINQ keywords — e.g. prefer myList.Where(x) to myList where x.

Array vs List

  • In general, prefer List<> over arrays for public variables, properties, and return types.
  • Prefer List<> when the size of the container can change.
  • Prefer arrays when the size of the container is fixed and known at construction time.
  • Prefer array for multidimensional arrays.

IEnumerable vs IList vs IReadOnlyList

  • For inputs use the most restrictive collection type possible, for example IReadOnlyCollection / IReadOnlyList / IEnumerable as inputs to methods when the inputs should be immutable.
  • For outputs, if passing ownership of the returned container to the owner, prefer IList over IEnumerable. If not transferring ownership, prefer the most restrictive option.

You can find more rules and guidelines below:

  1. C# Coding Conventions from Microsoft — https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions
  2. .Net Design Guidelines from Microsoft — https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/
  3. C# Style Guide from Google — google.github.io

Thanks for reading !!!

--

--