# .NET Coding Standards
These standards apply to all .NET code in the `dotnet/` directory. All contributors and AI agents must follow these rules.
## Runtime and Language
- **Target framework**: .NET 10
- **Language**: C# (latest stable version)
- **Nullable reference types**: Enabled project-wide (`enable`)
- **Implicit usings**: Enabled (`enable`)
## General Practices
- Follow the [Microsoft C# coding conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)
- Use `PascalCase` for public members, types, namespaces, and methods
- Use `camelCase` for local variables and parameters
- Prefix private fields with `_` (e.g., `_connectionCount`)
- Prefer `readonly` fields and immutable types where practical
- Use file-scoped namespaces
- Use primary constructors where they simplify the code
- Prefer pattern matching over type-checking casts
- Use `CancellationToken` on all async method signatures
- Use `ReadOnlySpan` and `ReadOnlyMemory` on hot paths to minimize allocations
- Prefer `ValueTask` over `Task` for methods that frequently complete synchronously
## Forbidden Packages
Do **NOT** use the following packages anywhere in the solution:
| Package | Reason |
|---------|--------|
| `FluentAssertions` | Use Shouldly instead |
| `Moq` | Use NSubstitute instead |
## Unit Testing
All unit tests live in `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/`.
### Framework and Libraries
| Purpose | Package | Version |
|---------|---------|---------|
| Test framework | `xUnit` | 3.x |
| Assertions | `Shouldly` | latest |
| Mocking | `NSubstitute` | latest |
| Benchmarking | `BenchmarkDotNet` | latest (for `Benchmark*` ports) |
### xUnit 3 Conventions
- Use `[Fact]` for single-case tests
- Use `[Theory]` with `[InlineData]` or `[MemberData]` for parameterized tests (replaces Go table-driven tests)
- Use `[Collection]` to control test parallelism when tests share resources
- Test classes implement `IAsyncLifetime` when setup/teardown is async
- Do **not** use `[SetUp]` or `[TearDown]` — those are NUnit/MSTest concepts
### Shouldly Conventions
```csharp
// Preferred assertion style
result.ShouldBe(expected);
result.ShouldNotBeNull();
result.ShouldBeGreaterThan(0);
collection.ShouldContain(item);
collection.ShouldBeEmpty();
Should.Throw(() => subject.DoSomething());
await Should.ThrowAsync(async () => await subject.DoSomethingAsync());
```
### NSubstitute Conventions
```csharp
// Create substitutes
var logger = Substitute.For>();
var repository = Substitute.For();
// Configure returns
repository.GetByIdAsync(Arg.Any(), Arg.Any())
.Returns(new Entity { Id = 1 });
// Verify calls
logger.Received(1).Log(
Arg.Is(LogLevel.Warning),
Arg.Any(),
Arg.Any