Design: C# and Windows Coding Guidelines
Summary
Add two new guideline files (csharp.md and windows.md) to ~/.claude/guidelines/ and update three existing files (general.md, best-practices-references.md, CLAUDE.md) for consistency.
Scope
- In scope: C# language conventions (.NET 9 / C# 13), Windows desktop via WinUI 3 / Windows App SDK, updates to existing cross-platform references
- Out of scope: ASP.NET Core / server-side, WPF, .NET MAUI, Entity Framework
Decisions
- Two files (language + platform) rather than one combined file
- WinUI 3 as the sole UI framework (WPF/MAUI deferred)
- .NET 9 / C# 13 baseline (not LTS .NET 8)
- Client-only — no server-side coverage
File 1: guidelines/csharp.md — C# / .NET Conventions
Header
# C# / .NET Conventions
Platform-specific guidance for C# development targeting .NET 9+.
Sections
1. References
Links to canonical Microsoft documentation:
2. Naming
PascalCasefor types, methods, properties, public fields, constants, namespacescamelCasefor parameters and local variables_camelCase(underscore prefix) for private instance fieldsIprefix for interfaces (e.g.,IDisposable)Asyncsuffix for async methods- Constants use
PascalCase, notSCREAMING_SNAKE_CASE
3. Nullable Reference Types
- Enable
<Nullable>enable</Nullable>in all projects - Treat warnings as design signals:
stringmeans non-null,string?means nullable - Avoid null-forgiving operator (
!) — prefer?? throwor guard clauses - Use
requiredproperties and constructor parameters for non-null initialization - Use
[NotNull],[MaybeNull],[NotNullWhen]fromSystem.Diagnostics.CodeAnalysisfor contracts
4. Immutability
- Use
readonlyfields andreadonly structby default. Introduce mutability only when required. - Prefer
System.Collections.Immutable(ImmutableList<T>,ImmutableDictionary<K,V>) for shared collections - Use
recordfor DTOs, API responses, domain events, value objects - Use
record struct/readonly record structfor small immutable value types - Prefer positional records for simple data carriers
- Use
initsetters andrequiredkeyword for mandatory properties - Use
withexpressions for non-destructive mutation - Contain mutable state behind
ObservableObject(UI) or thread-safe wrappers - Reserve
classwith mutable state for entities with identity semantics
5. Concurrency
async/awaitfor all async workConfigureAwait(false)in library code to avoid capturing sync context- Never use
.Resultor.Wait()— causes deadlocks - Never use
async voidexcept for event handlers - Accept
CancellationTokenin all async APIs - Use
ValueTask<T>only when method frequently completes synchronously - Use
Task.Runfor CPU-bound work, never on the UI thread
6. Dependency Injection
- Constructor injection via
Microsoft.Extensions.DependencyInjection - Use interface types for dependencies, not concrete types
Transientfor lightweight stateless,Scopedfor per-request,Singletonfor thread-safe shared- Never inject scoped into singleton (captive dependency)
- Use
IOptions<T>/IOptionsSnapshot<T>for configuration binding - Keep registrations in
Add*()extension methods for modularity
7. Logging
- Inject
ILogger<T>via constructor (category = consuming class) - Use structured message templates:
logger.LogInformation("Processing {OrderId}", orderId) - Never use string interpolation (
$"...") in log calls — bypasses structured logging - Use
[LoggerMessage]source generator attribute for high-performance hot paths - Configure levels via
appsettings.jsonper category
8. Linting and Formatting
.editorconfigat repo root for all code style rules- Enable
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>in.csproj - Enable
<AnalysisLevel>latest-recommended</AnalysisLevel>for Roslyn analyzers - Use
dotnet formatCLI for auto-fixing - Supplement with Roslynator or Meziantou.Analyzer for additional rules
9. Testing
- xUnit with
[Fact]and[Theory]/[InlineData]for parameterized tests - FluentAssertions for readable assertions
- NSubstitute for mocking
- Every change needs tests. Every bug fix needs a regression test.
- Prioritize unit tests over integration tests.
10. Secure Storage
- Use DPAPI (
ProtectedData.Protect/UnprotectwithDataProtectionScope.CurrentUser) for Windows-only local secrets - Use User Secrets (
Microsoft.Extensions.Configuration.UserSecrets) for development-time secrets only (plaintext JSON — not for production) - Never store tokens or credentials in plaintext config files or app settings
11. Feature Flags
IFeatureManagerinterface + local JSON config as default- Use
Microsoft.FeatureManagementNuGet package - Swap in Azure App Configuration for server-side flag evaluation later
12. Privacy
- Declare only required capabilities in
Package.appxmanifest— avoidbroadFileSystemAccessunless essential - Use DPAPI for local secret storage (see Secure Storage above)
- No PII in logs, even at debug level
- Respect user consent: app must remain functional if optional data collection is denied
13. Analytics
- Interface +
ILogger-backed implementation as the default - Same pattern as other platforms: no direct coupling to any analytics backend
File 2: guidelines/windows.md — Windows / WinUI 3 Conventions
Header
# Windows / WinUI 3 Conventions
Platform-specific guidance for Windows desktop development with WinUI 3 and the Windows App SDK.
Sections
1. References
- WinUI 3 / Windows App SDK
- Fluent 2 Design System
- Windows App SDK (GitHub)
- WinUI Gallery (GitHub)
- Windows Design Guidelines
2. Architecture
- MVVM with CommunityToolkit.Mvvm — source-generated
ObservableObject,RelayCommand, messaging - NavigationView + Frame for page-level navigation
- Navigation service abstraction in ViewModel layer — never manipulate Frame from code-behind
- Use Template Studio for project scaffolding
3. Fluent Design
- Use built-in WinUI 3 controls — they implement Fluent 2 natively
- Never custom-draw what a standard control can do
- Typography: Segoe UI Variable. Icons: Segoe Fluent Icons.
- Follow Windows design guidance for layout, spacing, and navigation patterns
4. Theming
- Tri-state theming: Light, Dark, High Contrast
- Set app-level via
Application.RequestedTheme, override per-element withFrameworkElement.RequestedTheme - Always use
ThemeResource(notStaticResource) for colors/brushes — enables runtime theme switching - Use semantic color resources (
TextFillColorPrimary,CardBackgroundFillColorDefault) not hex values - Define custom theme-aware colors in
ResourceDictionarywithDefault/Light/Darktheme dictionaries
5. Accessibility
- WinUI 3 controls expose UI Automation patterns automatically
- Set
AutomationProperties.Nameon interactive elements without visible text labels - Use
AutomationProperties.LabeledByfor form fields andAutomationProperties.LiveSettingfor dynamic content - High contrast support is automatic when using
ThemeResource— never hard-code colors - Test with Accessibility Insights for Windows
- Keyboard navigation: all interactive elements must be reachable via Tab, actionable via Enter/Space
Components MUST respond to these Windows accessibility settings:
| Setting | API / Detection | Action |
|---|---|---|
| High Contrast | AccessibilitySettings.HighContrast |
Automatic via ThemeResource — verify custom visuals adapt |
| Animations Disabled | UISettings.AnimationsEnabled |
Disable all custom animations and transitions |
| Text Scaling | UISettings.TextScaleFactor |
Layouts must not break up to 225% text scale |
| Color Filters | System setting | Ensure UI is usable with color vision deficiency filters |
| Narrator | UI Automation tree | All elements have Name, Role, and appropriate patterns |
| Keyboard Navigation | Focus management | All interactive elements reachable via Tab, actionable via Enter/Space |
| Dark Theme | Application.RequestedTheme |
Full dark theme support via ThemeResource |
| Caret Browsing | System setting | Non-interactive text should be navigable |
6. Localization
- MRT Core with
.reswresource files x:Uiddirective in XAML for multi-property localization (e.g.,x:Uid="SaveButton"maps toSaveButton.Content,SaveButton.AutomationProperties.Name)- Folder structure:
Strings/<language-tag>/Resources.resw - Code-behind access via
Microsoft.Windows.ApplicationModel.Resources.ResourceLoader - No hardcoded user-facing strings
7. Deep Linking / Protocol Activation
- Declare
<uap:Protocol Name="myapp"/>inPackage.appxmanifest - Handle via
AppInstance.GetActivatedEventArgs()inApp.OnLaunched - Parse URI to determine target page/state, navigate accordingly
- Use
AppInstance.FindOrRegisterForKey()for single-instancing (recommended for deep links)
8. App Notifications
- Use
AppNotificationManager+AppNotificationBuilderfluent API - Support text, images, buttons, progress bars, scheduled delivery
- Handle notification activation alongside protocol activation
- MSIX-packaged apps get notification identity automatically
9. High DPI / Display Scaling
- XAML layout uses effective pixels (epx) — scaling is automatic
- Provide bitmap assets at multiple scales:
.scale-100,.scale-125,.scale-150,.scale-200,.scale-400 - For custom rendering (Win2D, Direct3D), query
XamlRoot.RasterizationScaleand listen forRasterizationScaleChanged - Never hard-code pixel sizes in code-behind
10. MSIX Packaging
- Use single-project MSIX packaging model
- Declare capabilities minimally in
Package.appxmanifest - Sign packages with trusted certificate for sideloading
- Version numbering:
Major.Minor.Build.Revision, monotonically increasing
11. Logging
ILogger<T>(same conventions ascsharp.md)- Use ETW tracing (
EventSource) for system-level diagnostics and startup timing - Use XAML Live Visual Tree for debugging visual tree issues
12. Debug Mode
- Dev-only settings page guarded by
#if DEBUG - Include: feature flag overrides, analytics event log, environment info (version, OS, device)
- Access via navigation menu item visible only in debug builds
13. Concurrency
- Use
DispatcherQueue.TryEnqueueto marshal work back to the UI thread from background tasks - Never access UI elements from non-UI threads
- See
csharp.mdfor general async/await conventions
DispatcherQueue.TryEnqueue(() =>
{
StatusText.Text = "Updated from background";
});
14. RTL Layout Support
- Set
FlowDirection="RightToLeft"on the root element for RTL locales - WinUI 3 XAML layout handles leading/trailing automatically when FlowDirection is set
- Mirror icons with directional meaning (forward/back arrows)
- Test with RTL language packs installed
15. Design-Time Data
- Use
d:DataContextandd:DesignInstancefor XAML designer preview data - Use XAML Hot Reload for live iteration during development
File 3: Updates to guidelines/general.md
Add Windows/C# entries to existing platform-specific bullet lists:
| Rule | Addition |
|---|---|
| 4 (No blocking main thread) | **Windows/.NET**: async/await, Task.Run for CPU-bound, DispatcherQueue for UI updates |
| 8 (Post-generation verification) | Add dotnet build / dotnet test to build/test command list |
| 9 (Logging) | **Windows/.NET**: ILogger<T> from Microsoft.Extensions.Logging |
| 10 (Deep linking) | **Windows**: Protocol activation via uap:Protocol, AppInstance rich activation |
| 11 (Scriptable) | **Windows**: Protocol activation, command-line activation, AppInstance APIs |
| 12 (Accessibility from day one) | **Windows**: UI Automation patterns, Narrator testing, Accessibility Insights, 44epx minimum touch targets |
| 13 (Localizability) | **Windows**: .resw resource files with x:Uid in XAML, MRT Core ResourceLoader |
| 14 (RTL) | **Windows**: FlowDirection property. WinUI 3 handles leading/trailing automatically. |
| 16.3 (Secure storage) | Add DPAPI to the list: Keychain, EncryptedSharedPreferences, DPAPI, HttpOnly cookies |
| 20 (Debug mode) | **Windows**: Debug-only settings page, guarded by #if DEBUG |
| 21 (Linting) | Add row: `C# / .NET |
File 4: Updates to guidelines/best-practices-references.md
Add new section between "Web" and "Cross-Platform":
## Windows / .NET
- [C# Coding Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)
- [.NET Framework Design Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/)
- [WinUI 3 / Windows App SDK](https://learn.microsoft.com/en-us/windows/apps/winui/winui3/)
- [Fluent 2 Design System](https://fluent2.microsoft.design/)
- [Windows Accessibility](https://learn.microsoft.com/en-us/windows/apps/develop/accessibility)
- [MSIX Packaging](https://learn.microsoft.com/en-us/windows/msix/)
- [WinUI Gallery (GitHub)](https://github.com/microsoft/WinUI-Gallery)
File 5: Updates to ~/.claude/CLAUDE.md
Add to the guidelines listing:
- `~/.claude/guidelines/csharp.md` — C# / .NET
- `~/.claude/guidelines/windows.md` — Windows / WinUI 3
Implementation Order
- Create
guidelines/csharp.md - Create
guidelines/windows.md - Update
guidelines/general.md— add Windows entries to platform lists - Update
guidelines/best-practices-references.md— add Windows/.NET section - Update
~/.claude/CLAUDE.md— add guideline file listing - Run
install.shto symlink new files - Verify symlinks exist in
~/.claude/guidelines/