| name | csharp |
| description | Language-specific super-code guidelines for csharp. |
| risk | safe |
| source | community |
| date_added | 2026-06-16 |
C#: Idiomatic Efficiency Reference
Table of Contents
- LINQ & Collections
- Null Handling
- Async/Await
- Records & Pattern Matching
- Error Handling
- Resource Management
- Anti-patterns specific to C#
1. LINQ & Collections {#linq}
var result = new List<string>();
foreach (var item in items) {
if (item.IsActive) result.Add(item.Name.ToUpper());
}
var result = items
.Where(i => i.IsActive)
.Select(i => i.Name.ToUpper())
.ToList();
var grouped = new Dictionary<string, List<Item>>();
foreach (var item in items) {
if (!grouped.ContainsKey(item.Category))
grouped[item.Category] = new List<Item>();
grouped[item.Category].Add(item);
}
var grouped = items.GroupBy(i => i.Category)
.ToDictionary(g => g.Key, g => g.ToList());
if (items.Any(i => i.IsValid)) {
var first = items.First(i => i.IsValid);
}
var first = items.FirstOrDefault(i => i.IsValid);
if (first is not null) { ... }
Prefer method syntax for chains of 2+ operations. Query syntax is fine for complex joins.
2. Null Handling {#nulls}
string city = null;
if (user != null && user.Address != null) {
city = user.Address.City;
}
var city = user?.Address?.City;
var name = user != null ? user.Name : "Unknown";
var name = user?.Name ?? "Unknown";
if (OnChanged != null) OnChanged(this, args);
OnChanged?.Invoke(this, args);
if (name == null) throw new ArgumentNullException(nameof(name));
ArgumentNullException.ThrowIfNull(name);
Enable nullable reference types (<Nullable>enable</Nullable>) project-wide.
3. Async/Await {#async}
var result = GetDataAsync().Result;
var result = await GetDataAsync();
async void OnButtonClick() { await DoWork(); }
async Task OnButtonClick() { await DoWork(); }
var a = await FetchA();
var b = await FetchB();
var (a, b) = (await Task.WhenAll(FetchA(), FetchB())) switch
{
var r => (r[0], r[1])
};
var taskA = FetchA();
var taskB = FetchB();
var a = await taskA;
var b = await taskB;
public Task<int> GetValue() => Task.Run(() => ComputeSync());
public int GetValue() => ComputeSync();
Add ConfigureAwait(false) in library code. Omit in app/UI code.
4. Records & Pattern Matching {#records}
class Point {
public int X { get; init; }
public int Y { get; init; }
}
record Point(int X, int Y);
if (shape is Circle) {
var c = (Circle)shape;
return c.Radius * c.Radius * Math.PI;
} else if (shape is Rectangle) { ... }
return shape switch {
Circle { Radius: var r } => r * r * Math.PI,
Rectangle { Width: var w, Height: var h } => w * h,
_ => throw new ArgumentException($"Unknown shape: {shape}")
};
if (score >= 0 && score <= 100) { ... }
if (score is >= 0 and <= 100) { ... }
5. Error Handling {#errors}
try { Process(); }
catch (Exception ex) { logger.LogError(ex, "error"); }
try { Process(); }
catch (HttpRequestException ex) {
throw new ServiceException("upstream failure", ex);
}
catch (Exception ex) { throw ex; }
catch (Exception ex) { throw; }
try { return dict[key]; }
catch (KeyNotFoundException) { return defaultValue; }
return dict.TryGetValue(key, out var value) ? value : defaultValue;
6. Resource Management {#resources}
var conn = new SqlConnection(cs);
conn.Open();
conn.Dispose();
using var conn = new SqlConnection(cs);
conn.Open();
using (var reader = new StreamReader(path)) {
return reader.ReadToEnd();
}
using var reader = new StreamReader(path);
return reader.ReadToEnd();
7. Anti-patterns specific to C# {#antipatterns}
| Anti-pattern | Preferred |
|---|
string.Format("{0}", x) | $"{x}" string interpolation |
List<T> as public API return | IReadOnlyList<T> or IEnumerable<T> |
async void | async Task |
.Result / .Wait() on Task | await |
throw ex | throw (preserves stack trace) |
Manual IEquatable on data types | record |
object parameters | generics with constraints |
DateTime.Now | DateTime.UtcNow or DateTimeOffset |
| Mutable public fields | properties with { get; set; } or { get; init; } |
catch (Exception) { } (swallow all) | catch specific exceptions, rethrow unknown |
IDisposable without using | using declaration |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.