C# is a mature, powerful language—but many of its features are commonly misunderstood or misused, even by experienced developers. These mistakes don’t usually break your code, but they silently hurt performance, readability, and maintainability.
Let’s look at 10 C# features you’re probably using wrong—and how to fix them.
1. async / await — Thinking It Means “Multithreading”
Wrong usage
await DoWorkAsync();
Many developers assume async automatically runs code on another thread. It doesn’t.
Reality
Correct approach
await Task.Run(() => DoCpuBoundWork());
Use async for I/O-bound work, not CPU-heavy logic.
2. var — Using It Everywhere (or Nowhere)
Wrong usage
var data = GetData();
This hurts readability when the type isn’t obvious.
Better
List<User> users = GetUsers();
Rule of thumb
3. IEnumerable<T> — Assuming It’s Cached
Wrong usage
var users = GetUsers();
var count = users.Count();
var first = users.First();
If GetUsers() hits a database, this runs multiple queries.
Fix
var users = GetUsers().ToList();
IEnumerable<T> is lazy. Enumerate once when needed.
4. LINQ — Using It for Everything
Wrong usage
items.Select(x => {
SaveToDatabase(x);
return x;
}).ToList();
LINQ is for queries, not side effects.
Correct
foreach (var item in items)
{
SaveToDatabase(item);
}
LINQ should be declarative, not procedural.
5. == vs .Equals() — Assuming They’re the Same
Wrong assumption
obj1 == obj2
Reality
Best practice
obj1.Equals(obj2)
Always know which equality you need.
6. try-catch — Using It for Flow Control
Wrong
try
{
var value = int.Parse(input);
}
catch
{
// Ignore
}
Correct
if (int.TryParse(input, out var value))
{
// Use value
}
Exceptions are expensive. Don’t use them as if statements.
7. Dispose() — Forgetting using
Wrong
var stream = new FileStream(path, FileMode.Open);
Correct
using var stream = new FileStream(path, FileMode.Open);
If it implements IDisposable, dispose it—always.
8. readonly — Confusing It with Immutability
Wrong assumption
readonly List<int> numbers;
The reference is readonly—not the object.
Correct
IReadOnlyList<int> numbers;
readonly ≠ immutable.
9. null — Not Using Nullable Reference Types
Wrong
string name = null;
Correct (C# 8+)
string? name = null;
Enable it:
#nullable enable
Nullable reference types prevent bugs before runtime.
10. Records — Using Them Like Classes
Wrong
public record User
{
public string Name { get; set; }
}
This defeats the purpose of records.
Correct
public record User(string Name);
Records are for immutable, value-based data.
Final Thoughts
C# gives you powerful tools—but power without understanding leads to subtle bugs and performance issues.
If you:
Misuse async
Abuse LINQ
Ignore disposal
Skip nullable references
…your code works, but it doesn’t scale or age well.
Write C# that’s intentional, explicit, and predictable.