Skip to content

Commit 0c9defb

Browse files
committed
Add Post Draft
1 parent 47f469d commit 0c9defb

File tree

1 file changed

+194
-0
lines changed
  • content/posts/2025-XX-XX-stop-using-var

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
-- it's a calamitous atrocity --
2+
3+
If `clients` is an **enumeration (`IEnumerable<T>`)** rather than a **concrete collection (`List<T>`, `T[]`, etc.)**, then every time you iterate over `clients` (e.g. in a `foreach`, `.ToList()`, `.Count()`, etc.), the underlying sequence will be re-evaluated.
4+
5+
### What this means in practice:
6+
7+
* **If `GetClients()` returns a query** (like an EF Core LINQ query, or something built on `yield return`):
8+
9+
* Each enumeration re-runs the logic, potentially hitting the database or recomputing values.
10+
* Side effects (logging, network calls, DB queries) happen every time you iterate.
11+
* Performance can degrade unexpectedly.
12+
* **If it returns a materialized collection** (`List<T>`, `Array`, `HashSet<T>`, etc.):
13+
14+
* No problem. Multiple iterations are just reusing the already-fetched in-memory data.
15+
16+
### Example
17+
18+
```csharp
19+
var clients = context.Clients.Where(c => c.IsActive); // IQueryable/IEnumerable
20+
foreach (var c in clients) { ... } // Executes query
21+
foreach (var c in clients) { ... } // Executes query again!
22+
```
23+
24+
vs.
25+
26+
```csharp
27+
var clients = await context.Clients.Where(c => c.IsActive).ToListAsync();
28+
foreach (var c in clients) { ... } // Uses same in-memory list
29+
foreach (var c in clients) { ... } // Still in-memory, no extra DB call
30+
```
31+
32+
### Rule of thumb
33+
34+
If you’re not 100% sure whether the source is materialized, **force it with `.ToList()` or `.ToArray()`** when you assign:
35+
36+
```csharp
37+
var clients = (await GetClients()).ToList();
38+
```
39+
40+
👉 This guarantees that `clients` is a concrete collection, safe to reuse without surprises.
41+
42+
---
43+
44+
### 2. **Unintended numeric type**
45+
46+
```csharp
47+
var total = 1 / 2;
48+
```
49+
50+
* Type: `int` (since both operands are `int`).
51+
* Problem: `total` becomes `0`, not `0.5`. If you thought it was `double`, you’ll silently get wrong results.
52+
* Fix:
53+
54+
```csharp
55+
double total = 1 / 2.0; // 0.5
56+
```
57+
58+
---
59+
60+
So in short:
61+
62+
* With queries, `var` can hide that you’re holding a deferred-execution enumerable instead of actual data.
63+
* With arithmetic, `var` can lock you into an unintended (smaller or lossy) type.
64+
65+
---
66+
Perfect 👍 — here’s a **Top 10 `var` Pitfalls in C# Cheat Sheet**, each with a quick code sample and what can go wrong.
67+
68+
---
69+
70+
## 🔟 Common Pitfalls with `var`
71+
72+
### 1. **Deferred Execution (`IEnumerable` vs concrete collection)**
73+
74+
```csharp
75+
var clients = db.Clients.Where(c => c.IsActive); // IQueryable<Client>
76+
foreach (var c in clients) { } // DB query executes
77+
foreach (var c in clients) { } // Executes again!
78+
```
79+
80+
💥 Multiple queries when you thought it was cached.
81+
✅ Fix: `var clients = db.Clients.Where(...).ToList();`
82+
83+
---
84+
85+
### 2. **Anonymous Types Can’t Escape Scope**
86+
87+
```csharp
88+
var client = new { Name = "Alice", Age = 30 };
89+
```
90+
91+
💥 Can’t return this type from a method or store in a collection.
92+
✅ Use a real `Client` class.
93+
94+
---
95+
96+
### 3. **Async Return Confusion (`Task<T>` vs `T`)**
97+
98+
```csharp
99+
var text = File.ReadAllTextAsync("file.txt"); // Task<string>
100+
Console.WriteLine(text.Length); // ❌ Not what you think
101+
```
102+
103+
💥 Accidentally working with the `Task`, not the result.
104+
✅ `var text = await File.ReadAllTextAsync("file.txt");`
105+
106+
---
107+
108+
### 4. **Numeric Overflow / Wrong Type**
109+
110+
```csharp
111+
var big = 100000 * 100000; // int
112+
Console.WriteLine(big); // ❌ Overflow
113+
```
114+
115+
💥 Silent overflow since it’s `int`.
116+
✅ `long big = 100000L * 100000;`
117+
118+
---
119+
120+
### 5. **Integer Division Surprise**
121+
122+
```csharp
123+
var ratio = 1 / 2; // int
124+
Console.WriteLine(ratio); // 0
125+
```
126+
127+
💥 If you expected a `double`, you’re wrong.
128+
✅ `double ratio = 1 / 2.0;`
129+
130+
---
131+
132+
### 6. **Boxing and Performance Issues**
133+
134+
```csharp
135+
var number = GetObject(); // object
136+
int value = (int)number; // boxing/unboxing
137+
```
138+
139+
💥 If you thought it was already `int`, perf and runtime errors appear.
140+
✅ Declare the concrete type.
141+
142+
---
143+
144+
### 7. **Nullable Value Types Hidden**
145+
146+
```csharp
147+
var age = dbRow["Age"]; // object (nullable DB field)
148+
int x = (int)age; // ❌ NullReferenceException
149+
```
150+
151+
💥 You think it’s `int`, but it’s really `int?` or `object`.
152+
✅ Explicitly handle nullable types.
153+
154+
---
155+
156+
### 8. **Implicitly Wrong Collection Type**
157+
158+
```csharp
159+
var clients = new[] { "Alice", "Bob" }; // string[]
160+
```
161+
162+
💥 If you expected `List<string>`, you lose `List` methods.
163+
✅ Be explicit: `List<string> clients = new() { "Alice", "Bob" };`
164+
165+
---
166+
167+
### 9. **Dynamic APIs Returning `object`**
168+
169+
```csharp
170+
var json = JsonSerializer.Deserialize<object>("{}");
171+
```
172+
173+
💥 You think `json` is a dictionary, but it’s just `object`. Casting headaches follow.
174+
✅ Explicitly specify generic type: `Deserialize<Dictionary<string, object>>()`.
175+
176+
---
177+
178+
### 10. **Reduced Readability for Teams**
179+
180+
```csharp
181+
var x = MethodThatReturnsSomething();
182+
```
183+
184+
💥 Nobody knows what `x` is without hovering or jumping to definition. Maintenance pain.
185+
✅ Only use `var` when the type is obvious from the right-hand side.
186+
187+
---
188+
189+
## ✅ Rule of Thumb
190+
191+
* Use `var` when the type is **clear and obvious** (e.g. `var client = new Client();`).
192+
* Avoid it when the type is **ambiguous, surprising, or critical to correctness** (async, queries, arithmetic).
193+
194+
---

0 commit comments

Comments
 (0)