Instruction file imported from markheydon/solo-dev-board (
.github/instructions/dotnet-framework.instructions.md). Copyright stays with the author.
.NET 10 Development
Build and Compilation Requirements
- Use
dotnet buildanddotnet testfor solution and project builds. - Use
dotnet restorebefore build/test when dependencies may have changed.
Project File Management
SDK-Style Project Structure
This repository uses SDK-style projects:
- Implicit file inclusion: New source files are usually auto-included by SDK-style projects.
- Modern target framework: Use
<TargetFramework>net10.0</TargetFramework>. - Nullable and implicit usings: Keep
<Nullable>enable</Nullable>and<ImplicitUsings>enable</ImplicitUsings>enabled.
NuGet Package Management
- Manage packages with
dotnet add package,dotnet remove package, and central package versioning if introduced. - Keep package choices aligned with the architecture and avoid unnecessary dependencies.
- Prefer stable package versions unless pre-release is explicitly required.
- When changing the
MudBlazor<PackageVersion>inDirectory.Packages.props, refresh.agents/skills/mudblazor/in the same change (see that skill’sSKILL.md).
C# Language Version
- Use C# 14 language features where they improve readability and maintainability.
- Follow repository conventions for file-scoped namespaces, nullable reference types, and primary constructors where appropriate.
Testing Baseline
- Test framework:
xUnitv3 (xunit.v3package; test projects use<OutputType>Exe</OutputType>). - Mocking framework:
NSubstitute. - Component tests:
bUnitin the App test project. - End-to-end tests:
Playwrightfor key user journeys (separate fromdotnet test). - AppHost: do not test .NET Aspire AppHost modelling or orchestration.
- Assertions: xUnit built-in
Assert.*methods. Do not use FluentAssertions, AwesomeAssertions, Shouldly, Moq, NUnit, or MSTest (see DEC-006 and DEC-016). - Naming convention:
MethodUnderTest_Scenario_ExpectedOutcome. - Structure tests using Arrange / Act / Assert with blank lines between sections.
Environment Considerations
- Respect the current execution environment rather than assuming Windows.
- When running in WSL or Linux terminals, use POSIX paths and bash-safe commands.
- When running in Windows PowerShell, use Windows paths and PowerShell-native command syntax.
- If VS Code is attached to WSL, treat the shell environment as Linux even when the host machine is Windows.
Common .NET 10 Pitfalls and Best Practices
Async/Await Patterns
- ConfigureAwait(false): Use in reusable library code where a captured context is unnecessary:
var result = await SomeAsyncMethod().ConfigureAwait(false); - Avoid sync-over-async: Do not use
.Result,.Wait(), or.GetAwaiter().GetResult().
DateTime Handling
- Use DateTimeOffset for timestamps: Prefer
DateTimeOffsetoverDateTimefor absolute time points - Specify DateTimeKind: When using
DateTime, always specifyDateTimeKind.UtcorDateTimeKind.Local - Culture-aware formatting: Use
CultureInfo.InvariantCulturefor serialization/parsing
String Operations
- StringBuilder for concatenation: Use
StringBuilderfor multiple string concatenations - StringComparison: Always specify
StringComparisonfor string operations:string.Equals(other, StringComparison.OrdinalIgnoreCase)
Memory Management
- Dispose pattern: Implement
IDisposableproperly for unmanaged resources - Using statements: Always wrap
IDisposableobjects in using statements - Avoid large object heap: Keep objects under 85KB to avoid LOH allocation
Configuration
- Use Options pattern: Bind configuration to strongly typed options and validate startup configuration.
- Use environment-specific settings: Keep configuration in
appsettings.jsonandappsettings.{Environment}.json.
Exception Handling
- Specific exceptions: Catch specific exception types, not generic
Exception - Don't swallow exceptions: Always log or re-throw exceptions appropriately
- Use using for disposable resources: Ensures proper cleanup even when exceptions occur
Performance Considerations
- Avoid boxing: Be aware of boxing/unboxing with value types and generics
- String interning: Use
string.Intern()judiciously for frequently used strings - Lazy initialization: Use
Lazy<T>for expensive object creation - Avoid reflection in hot paths: Cache
MethodInfo,PropertyInfoobjects when possible