# Idiomatic C# and Common Pitfalls — C#/.NET

Source: https://www.skillbyai.com/en/dotnet/p-idioms

> Follow naming conventions and avoid well-known C# mistakes.

## Conventions and traps

**Naming**: `PascalCase` for types, methods, properties and constants; `camelCase` for locals and parameters; `_camelCase` for private fields; interfaces start with `I`; async methods end with `Async`. **Strings**: compare with an explicit `StringComparison` (`Ordinal` or `OrdinalIgnoreCase` for identifiers, culture-aware only for user-facing text), because `ToLower()` and culture rules cause bugs such as the Turkish "I" problem. **Dates**: store and compute in UTC (`DateTimeOffset.UtcNow`) and convert for display. **Equality**: override `Equals` and `GetHashCode` together, or use records. **Async**: no `async void`, no `.Result`. **Resources**: `using` for everything disposable. **LINQ**: watch for multiple enumeration and accidental N+1 queries in EF Core. **Floating point**: never compare `double` values with `==`; use a tolerance, or `decimal` for money.

## Spot the bug

Each pair shows a common mistake and the idiomatic fix.

```cs
// 1. culture-sensitive comparison of an identifier
if (role.ToLower() == "admin") { }                          // bug-prone
if (string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase)) { }

// 2. local time stored in the database
var created = DateTime.Now;                                   // ambiguous
var createdUtc = DateTimeOffset.UtcNow;

// 3. blocking on async code
var data = client.GetStringAsync(url).Result;                 // can deadlock, wastes threads
var data2 = await client.GetStringAsync(url);

// 4. comparing doubles
bool same = 0.1 + 0.2 == 0.3;                                 // false
bool close = Math.Abs((0.1 + 0.2) - 0.3) < 1e-9;
```

## Read the analyzer message

Many of these pitfalls already have analyzer warnings (for example CA1309 and CA1862 for string comparisons). When a warning appears, read the linked documentation before suppressing it.

**Quiz:** Which comparison is recommended for checking a role name such as "admin" regardless of case?

- [x] string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase)
- [ ] role.ToLower() == "admin"
- [ ] role.ToUpper(CultureInfo.CurrentCulture) == "ADMIN"
- [ ] role.GetHashCode() == "admin".GetHashCode()

*Answer:* string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase). Ordinal ignore-case comparison is culture-independent and does not allocate new strings.
