पाठ 24 / 25

Idiomatic C# and Common Pitfalls

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.

// 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.

त्वरित जाँच: Which comparison is recommended for checking a role name such as "admin" regardless of case?

  • 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.