top of page

C# — Style Guide Cheat Sheet


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.




Source: Medium


The Tech Platform

0 comments

Comments


bottom of page