C# — Style Guide Cheat Sheet. Write clearly, write beautifully!
By: Nikita Starichenko
Tags: C Sharp Programming, Code, Guidelines, Dotnet, Software Development

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.

/ / 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 .

, e.g. . Filenames and directory names are PascalCase , e.g. MyFile.cs .

, e.g. . Choose easily readable identifier names, e.g. a property named HorizontalAlignment is more English-readable than AlignmentHorizontal .

is more English-readable than . Favor readability over brevity, e.g. a property name CanScrollHorizontally is better than ScrollableX (an obscure reference to the X-axis).

is better than (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.

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>();

, or 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.

for returns that are not also inputs. Place out parameters after all other parameters in the method definition.

parameters after all other parameters in the method definition. ref should be used rarely, when mutating an input is necessary.

should be used rarely, when mutating an input is necessary. Do NOT use ref as an optimisation for passing structs.

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.

to pass a modifiable container into a method. 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.

) 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 .

should always be made . 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.

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.

over arrays for public variables, properties, and return types. Prefer List<> when the size of the container can change.

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.

/ / 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: