language-csharplisted
Install: claude install-skill lugassawan/swe-workbench
# 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);