🧹 Formatting Isn't Optional
Clean code starts with clean structure. Saying formatting doesn't matter is like saying your team doesn't need desks.
Use consistent indentation.
Place curly braces on the same line (K&R style).
Avoid extra spacing and empty lines.
Your IDE should never be fighting your eyes.
🎯 Less Code, Better Code
Use expression-bodied members where it makes sense. Drop redundant private
and this
if the context is clear. Let the compiler do the typing with new()
when the target type is obvious.
// Before
private string name;
public string GetName() { return name; }
// After
private string name;
public string GetName() => name;
📘 Explicit Types
var
is great, but not always. Prefer explicit types when:
The type is generic or not immediately obvious
You're reviewing unfamiliar code
Left and right types don't match (
IReadOnlyCollection<>
vsList<>
)
Be clear about your intentions, not just your implementation.
🧠 Naming Matters
Name variables after what they hold. Name methods after what they do.
If a method is called LoadCustomer
, it should do just that.
If you can't find the right name, the code might be doing too much.
🧩 Small Methods, Small Classes
A method should do one thing. If it's catching exceptions and writing logs, split it.
Class names like MongoHandler
and MariaDbHandler
might signal a design problem.
Instead, move logic into focused classes and let naming become natural.
🏗️ Solution Structure
More projects = more clarity.
Three-layer setups (Application, Domain, Infrastructure) are common. But if you're stuffing unrelated classes in the same project, it's time to split.
Every time you want to create a new folder, consider creating a new project instead.
Keep interfaces and DTOs separate from implementations.
🔗 Avoid Transitive Dependencies
In .NET Core, project references include everything their dependencies include.
This leads to hidden dependencies and weird cross-project links.
Keep your reference tree flat and predictable.
Use Directory.Build.props
to control what's exposed.
✨ Embrace Modern C#
Modern C# is packed with features that reduce code and improve reliability:
Records
Use records for DTOs. They’re immutable and concise.Global Usings
Keep files cleaner by avoiding repeated imports.Switch Expressions & Pattern Matching
More readable than nestedif
blocks.Nullable Reference Types
Cut down onNullReferenceException
at compile time.Code Generators
Automate boilerplate. Let the compiler help you write less.
🧩 Interfaces Are Intentions
Use interfaces to define contracts, not just types.
Interfaces like IReadOnlyCollection<>
help prevent misuse of mutable data.
They make testing simpler and keep your code focused.