This document describes how agentic coding tools should work in this repository. It summarizes how to build, test, and the coding conventions already used across the codebase. Follow these rules unless a change explicitly requires deviation.
- Language/runtime: C# multi-targeted (netstandard2.0 + .NET 6/7/8/9, optional .NET 10)
- Solution file:
DisposeScope.sln - Core library:
Dispose.Scope - Tests:
tests/Dispose.Scope.Tests - Benchmarks:
benchmarks/Benchmark*(BenchmarkDotNet) - CI: GitHub Actions using
dotnet build+dotnet test
This is a low-level performance‑sensitive library focused on allocation control and pooling. Favor clarity, determinism, and minimal allocations.
dotnet restore DisposeScope.slndotnet build DisposeScope.sln -c Releasedotnet build DisposeScope.slndotnet testdotnet test tests/Dispose.Scope.Tests/Dispose.Scope.Tests.csprojdotnet test tests/Dispose.Scope.Tests/Dispose.Scope.Tests.csproj --filter FullyQualifiedName~ClassNameExamples:
# single test class
dotnet test --filter FullyQualifiedName~DisposeScopeTests
# single test method
dotnet test --filter FullyQualifiedName~DisposeScopeTests.BeginScope_ReusesPoolsBenchmarks are not part of CI and should be run manually.
dotnet run -c Release --project benchmarks/Benchmark/Benchmark.csprojRun benchmarks only in Release mode and on an idle machine.
- No standalone linter is configured
- Rely on compiler warnings and
.editorconfiggenerated by SDK - Do not auto‑reformat code unless changing the touched lines
- Optimize for readability first, allocations second
- Avoid unnecessary abstractions
- Prefer explicit code over clever code
- Public APIs are stable: breaking changes require strong justification
- 4‑space indentation
- One type per file
- Braces on new lines (Allman style)
- Keep methods short and single‑purpose
- Blank line between logical sections
Example:
public void DoWork()
{
if (condition)
{
Execute();
}
}- Place
usingstatements at the top of the file - Group system namespaces first, then third‑party, then local
- Remove unused
usingdirectives
Order:
using System;
using System.Collections.Generic;
using Collections.Pooled;
using Dispose.Scope;Global usings may be introduced only if they clearly reduce repetition.
- Namespaces:
Dispose.Scope.* - Types:
PascalCase - Methods:
PascalCase - Public members:
PascalCase - Private fields:
_camelCase - Locals and parameters:
camelCase
Avoid abbreviations unless they are well‑established (e.g., vm, id).
- Nullable reference types are enabled
- Use
string?/T?when null is valid - Do not suppress nullability warnings without explanation
- Prefer explicit types over
varwhen the type is not obvious
Acceptable:
var list = new PooledList<int>(); // obviousAvoid:
var x = GetSomething(); // unclear- Fail fast for programmer errors
- Use
ArgumentException/ArgumentNullExceptionfor invalid inputs - Do not swallow exceptions
- Avoid catching
Exceptionunless rethrowing with context
This is a library: do not log to console or swallow failures.
- Avoid LINQ in hot paths unless measured
- Dispose pooled collections deterministically
- Prefer
using varover explicitDispose()calls - Do not allocate in loops unless unavoidable
- Bench before and after performance‑critical changes
DisposeScope usage:
using (_ = DisposeScope.BeginScope())
{
// pooled allocations
}- Tests should be deterministic and allocation‑aware
- Prefer clear Arrange / Act / Assert sections
- Avoid time‑based assertions
- Do not rely on execution order
- CI uses
.github/workflows/buildandtest.yml - CI builds with multiple SDKs (6/7/8/9/10) but the library remains
netstandard2.0for broad compatibility - Linux CI environment
- All tests must pass before merging
There are no Cursor (.cursor/) or Copilot instruction files present in this repository at this time.
- Touch only relevant files
- Preserve existing public API behavior
- Add tests for behavioral changes
- Do not reformat unrelated code
If unsure, ask before making structural or breaking changes.