Implement multithreading and asynchronous processing

Implement multithreading and asynchronous processing

When using async and await keep in mind that you should never have a method marked async without any await statements. You should also avoid returning void from an async method except when it’s an event handler.

Rethrowing an exception

Make sure that you don’t swallow any exception details when rethrowing an exception. Throw a new exception that points to the original one when you want to add extra information; otherwise, use the throw keyword without an identifier to preserve the original exception details.

Create and use types

Create Types

It’s important to know the different types that are available in C#. A value type should be used for small, immutable objects that are used a lot. In all other situations, use a reference type.

Extension methods

Remember that the difference between a regular static method and an extension method is the special this keyword for the first argument.

Consume types

Explicit conversions

Make sure that you know the difference between an implicit and explicit conversion. An explicit conversion is called casting and always needs some special syntax.

Enforce encapsulation

Using properties

Always favor properties over fields for public members. An automatically implemented property looks like a field to the outside world, but you can always add extra behavior when necessary.

Create and implement a class hierarchy

Abstract classes

Make sure that you know the difference between an interface and an abstract class. An interface has no implementation code. An abstract class can choose to implement methods or leave it to the derived class.

Manage the object life cycle


It’s important to know the difference between implementing IDisposable and a finalizer. Both clean up your object, but a finalizer is called by the garbage collector, and the Dispose method can be called from code.

Manipulate strings

Manipulating strings

Because of the immutability of the string type, all string operations return a new string. Make sure that you use this value instead of the original string.

Validate application input

Validating application input

It’s important to know that when you are parsing user input, the best choice is the TryParse method. Throwing exceptions for “normal” errors is not a best practice. TryParse just returns false when the value can’t be parsed.

Perform symmetric and asymmetric encryption


Try to remember the differences between symmetric and asymmetric algorithms. A symmetric algorithm uses one key; an asymmetric algorithm uses two: a key pair that consists of both a public and a private key.

Manage assemblies

Versioning assemblies

The probing option can be used only to point to locations that are relative to the application path. If you want to locate assemblies somewhere else, you have to use the codebase element.

Debug an application

Program database files and symbols

Remember how important it is to save your PDB files somewhere. If you throw them away, you immediately lose the opportunity to debug that specific build of your application.

Data Access - Perform I/O operations

File paths

Never try to manually add strings together to form a path. Always use the Path class when combining multiple strings together to form a legal path.