Skip to content
Back to skills

Language Csharp

ASecurity

C# and .NET idioms — .NET 8 LTS, C# NRT, records, value semantics, switch expressions, async/await, Task, ValueTask, CancellationToken, ConfigureAwait, IOptions<T>, LINQ, Span<T>, ArrayPool, hot path, allocation profiling, and performance. Auto-load when working with .cs files, .csproj, .sln, Directory.Build.props, or when the user mentions C#, dotnet, .NET 8, C# NRT, NRT, records, value semantics, switch expressions, Task, ValueTask, CancellationToken, ConfigureAwait, LINQ, Span, or hot-path...

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
developmentc#expresstestingapidatabaseperformance

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 3, 2026

npx -y skills add lugassawan/swe-workbench --skill language-csharp --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Language Csharp?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Language Csharp
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lugassawan-language-csharp/badge)](https://www.skillsdirectory.com/skills/lugassawan-language-csharp)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: language-csharp
description: C# and .NET idioms — .NET 8 LTS, C# NRT, records, value semantics, switch expressions, async/await, Task, ValueTask, CancellationToken, ConfigureAwait, IOptions<T>, LINQ, Span<T>, ArrayPool, hot path, allocation profiling, and performance. Auto-load when working with .cs files, .csproj, .sln, Directory.Build.props, or when the user mentions C#, dotnet, .NET 8, C# NRT, NRT, records, value semantics, switch expressions, Task, ValueTask, CancellationToken, ConfigureAwait, LINQ, Span, or hot-path code.
---

# C# / .NET

## .NET 8 project shape
- Prefer SDK-style projects with explicit `TargetFramework` (`net8.0`) and shared defaults in `Directory.Build.props`.
- Keep nullable reference types enabled for new code: `<Nullable>enable</Nullable>`.
- Use `ImplicitUsings` when the repository already does; avoid hand-maintaining noisy common imports.
- Keep application, domain, infrastructure, and test projects separate when boundaries are real, not just for ceremony.

```xml
<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <Nullable>enable</Nullable>
  <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
```

## Nullable reference types
- Treat warnings as design feedback, not noise. Model absence with `T?`, `required`, or a domain type.
- Validate nullable inputs at boundaries; keep internals non-null where possible.
- Use `ArgumentNullException.ThrowIfNull(value)` for guard clauses.
- Avoid `!` except when bridging a framework or serializer limitation; leave a short reason.

```csharp
public sealed class User
{
    public required string Email { get; init; }
    public string? DisplayName { get; init; }
}
```

## Records and value semantics
- Use `record` or `readonly record struct` for immutable value-like data.
- Use classes for identity, lifecycle, mutation, or behavior-heavy objects.
- Be deliberate with `with`: it is copy-with-change, not validation unless constructors enforce invariants.

```csharp
public sealed record Money(decimal Amount, string Currency);

var discounted = price with { Amount = price.Amount * 0.9m };
```

## Pattern matching
- Use patterns for shape-based branching, parsing, and closed domain states.
- Prefer switch expressions when every case returns a value.
- Keep guards (`when`) simple; complex decisions deserve named methods.

```csharp
return command switch
{
    CreateUser(var email) when email.Contains('@') => Create(email),
    DeleteUser(var id) => Delete(id),
    _ => throw new InvalidOperationException("unsupported command")
};
```

## Async and cancellation
- Use `async`/`await` all the way. Avoid `.Result`, `.Wait()`, and blocking over async work.
- Accept and pass `CancellationToken` through I/O, database, and long-running operations.
- In libraries, use `ConfigureAwait(false)` when code does not need a captured context; in modern app code, follow the repo's convention.
- Prefer `Task.WhenAll` for independent work; avoid unobserved fire-and-forget tasks.

```csharp
public async Task<User> GetUserAsync(string id, CancellationToken cancellationToken)
{
    ArgumentException.ThrowIfNullOrWhiteSpace(id);
    return await repository.FindAsync(id, cancellationToken).ConfigureAwait(false)
        ?? throw new UserNotFoundException(id);
}
```

## Dependency injection and options
- Depend on abstractions at boundaries, but do not create interfaces for every class by habit.
- Use constructor injection for required collaborators; avoid service locator patterns.
- Bind configuration to option records and consume `IOptions<T>`, `IOptionsSnapshot<T>`, or `IOptionsMonitor<T>` based on lifetime needs.
- Validate options at startup when invalid configuration should fail fast.

```csharp
public sealed record RetryOptions
{
    public int MaxAttempts { get; init; } = 3;
}

public sealed class Worker(IOptions<RetryOptions> options)
{
    private readonly RetryOptions retry = options.Value;
}
```

## LINQ and performance
- Use LINQ for clear transformations, filtering, grouping, and projections.
- Prefer `Any()` over `Count() > 0`, and avoid repeated enumeration of deferred queries.
- In hot paths, benchmark before replacing readable LINQ with loops.
- Use `Span<T>`, pooling, and allocation-aware APIs only when profiling shows they matter.

```csharp
var activeEmails = users
    .Where(user => user.IsActive)
    .Select(user => user.Email)
    .ToArray();
```

## Doc comments
- **XML doc** — `/// <summary>` one concise sentence; add `<param>`/`<returns>` only when they carry information the signature doesn't (units, valid ranges, ownership).

```csharp
/// <summary>Returns the user's active orders, most recent first.</summary>
public IReadOnlyList<Order> ActiveOrders(string userId) { ... }
```

## Tooling
- **Imports/Format:** `dotnet format`
- **Lint:** Roslyn analyzers (`<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>` in csproj); `dotnet format --verify-no-changes` as formatting gate in CI
- **Test:** `dotnet test` (see Testing below)

## Testing
- xUnit, NUnit, and MSTest are all fine; follow the repository's existing framework.
- Use fluent assertions when already present, and keep tests behavior-focused.
- Mock external boundaries, not records, value objects, or simple domain behavior.

## Avoid
- Disabling nullable warnings instead of fixing the contract.
- Blocking on tasks with `.Result`, `.Wait()`, or `GetAwaiter().GetResult()`.
- Treating dependency injection as a reason to hide every constructor behind an interface.
- Rewriting clear LINQ into loops without a measured performance reason.
- Making ASP.NET conventions the default for non-web .NET code.

Files in this skill

  • SKILL.md5.5 KB
  • triggers.txt373 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.