Przejdź do treści
Biblioteka skilli
Programowanie · Budowanie i kod

coding-standards

/coding-standards

Opisuje standardy C# i .NET dla nowych plików: C# 14 i .NET 10, nazewnictwo, formatowanie, dokumentacja XML, konwencje WinForms i idiomy wydajności.

Repozytorium
winforms ↗
Licencja
MIT
Ostatnia zmiana repozytorium
22.10.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 22.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Opisuje standardy C# i .NET dla nowych plików: C# 14 i .NET 10, nazewnictwo, formatowanie, dokumentacja XML, konwencje WinForms i idiomy wydajności.

Oryginalny opis (EN)

C# and .NET coding standards for generating new code files. Use when creating new classes, methods, controls, tests, or any new C# / VB source files in this repository. Covers C# 14 / .NET 10 patterns, naming, formatting, XML docs, WinForms conventions, and performance idioms.

Jak działa

  1. Target Framework
  2. Language Version
  3. General Assumptions
  4. Type Usage and var Policy
  5. Null Checking
  6. Naming and Field Conventions
  7. Formatting and Line Length
  8. Pattern Matching and Switch Expressions
  9. Readability
  10. Error Handling and Argument Validation
Sekcje z nagłówków SKILL.md, w oryginale · 417 linii, 1 805 słów
Podgląd SKILL.md
---
name: coding-standards
description: >-
  C# and .NET coding standards for generating new code files. Use when creating
  new classes, methods, controls, tests, or any new C# / VB source files in this
  repository. Covers C# 14 / .NET 10 patterns, naming, formatting, XML docs,
  WinForms conventions, and performance idioms.
metadata:
  author: dotnet-winforms
  version: "1.0"
---

# Coding Standards — New Code Generation

These rules apply whenever you **generate new** C# or VB.NET source files in
this repository. For modernizing or refactoring *existing* files, see the
`code-modernization` skill instead.

## Target Framework

* Default target is **.NET 10.0** (`net10.0`).
* Some files target .NET Framework or are multi-targeted — check the project
  file before generating.
* Do not edit files under `eng/common/`.
* Follow all rules defined in `.editorconfig`.

## Language Version

Use **C# 14** features and patterns. Key features to prefer:

| Feature | Example |
|---|---|
| Extension members (extension blocks) | `extension(string s) { public bool IsBlank() => ... }` |
| `field` keyword in properties | `set => field = value ?? throw ...;` |
| Null-conditional assignment | `customer?.Order = GetOrder();` |
| `nameof` on unbound generics | `nameof(List<>)` |
| Lambda modifiers without types | `(text, out result) => int.TryParse(text, out result)` |
| Partial constructors / events | `partial MyClass() { }` |
| First-class `Span<T>` conversions | Implicit `T[]` → `Span<T>` / `ReadOnlySpan<T>` |

## General Assumptions

* **Namespace imports** are defined in a global usings file — omit standard
  `using` directives unless the import is non-obvious.
* **Nullable Reference Types** are enabled — annotate all new code accordingly.
* Use **file-scoped namespace** declarations.

## Type Usage and `var` Policy

Apply the following rules **in priority order**:

1. **Never use `var` for primitive types.** Always spell out `int`, `string`,
   `bool`, `double`, `float`, `decimal`, `char`, `byte`, `long`, etc.

```csharp
// REQUIRED — explicit types for primitives
int count = 5;
string name = "Button";
bool isVisible = true;
```

2. **Use `var` when the type is already visible or clearly implied on the
   same line.** Repeating the type degrades readability. This applies to:

   * **Casts:** `var foo = (SomeType) bar;`
   * **`as` casts:** `var button = item as ToolStripDropDownButton;`
   * **Generic methods with explicit type argument(s):** Assume the return
     type matches the generic type parameter — even when the method
     signature technically returns a base type — because the `<T>` already
     tells the reader what they are getting back:
     `var host = this.GetService<IDesignerHost>();`
     `var session = provider.GetRequiredService<DesignerSession>();`
   * **`out var` in generic methods that name the type:**
     `site.TryGetService<INestedContainer>(out var container)` — the `<T>`
     already specifies the type.
   * **Methods whose name contains or implies the return type:** When the
     method name clearly communicates the type being returned, `var` is
     preferred because the type is already readable from the call itself:
     `var componentType = component.GetType();`
     `var resourceStream = BitmapSelector.GetResourceStream(type, name);`
     `TryLoadBitmapFromStream(stream, out var resourceBitmap)`

```csharp
// GOOD — var when type is visible or implied on the line
var designerHostShim = (IDesignerHostShim)designerHost;
var host = this.GetService<IDesignerHost>();
var manager = host.GetExport<ViewModelClientFactoryManager>();
var componentType = component.GetType();
var resourceStream = BitmapSelector.GetResourceStream(componentType, componentType.Name + ".bmp");
service.TryGetValue<AppSettings>(out var settings);
```

3. **Use `var` for deeply nested or complex generic types** where the full type
   name is unwieldy:

```csharp
using var pooledList = ListPool<IComponent>.GetPooledObject();
var result = pooledList.Object;
var (key, value) = dictionary.First();   // tuple deconstruction
```

4. **Use explicit types when neither the variable name nor the surrounding
   context reveals the type.** If a reader would need to navigate to a method
   signature to understand what a variable holds, spell the type out.

```csharp
// REQUIRED — explicit when type is not obvious
CreateViewModelResponse response = session.GetWinFormsEndpoints().DocumentOutline.CreateViewModel(session.Id);
TreeViewHitTestInfo hitTestInfo = _treeView.HitTest(e.Location);
```

5. **Prefer target-typed `new()` over `var`** when the type is visible on the
   left — clean construction without redundancy:

```csharp
// Before
Dictionary<string, List<int>> map = new Dictionary<string, List<int>>();
var map = new Dictionary<string, List<int>>();

// After
Dictionary<string, List<int>> map = new();
Button saveButton = new();
```

**Do NOT use target-typed `new()` when the type isn't visible on the same line:**

```csharp
// DO — type is visible on the right, so var is fine:
var map = new Dictionary<string, List<int>>();

// DON'T — _map is a backing field declared elsewhere,
// so the type isn't visible here. Too implicit.
_map = new();
```

6. **`var` is always fine for tuple deconstruction:**

```csharp
var (nodes, images) = viewModel.UpdateTreeView(displayStyle);
var (key, value) = dictionary.First();
```

7. Using Collection expressions:

```csharp
// Before
List<string> items = new List<string>();

// After
List<string> items = [];
```

* Consider collection expressions also for methods that return collections, e.g.:

```csharp
// Before
Control[] controls = _view.Controls.Cast<Control>().ToArray();

// After
Control[] controls = [.. _view.Controls.Cast<Control>()];
```

* Avoid, however, collection expressions, when constructable array/collection
  type are necessary in the context, e.g.:

```csharp
// Be careful! Will not compile, we need a constructable array type in this
// context, so collection initializer syntax is not possible here.
Control CreateErrorControlForMessage(string message) 
   => CreateErrorControl([new InvalidOperationException(message)]);

// In this case we need:
Control CreateErrorControlForMessage(string message) 
   => CreateErrorControl(new[] { new InvalidOperationException(message) });
```

## Null Checking

* **Use `is null` / `is not null`** — never `== null` or `!= null`.
* Use coalesce: `value ?? "default"`, `value ??= GetDefault()`.

## Naming and Field Conventions

| Element | Convention |
|---|---|
| `private` / `internal` instance fields | `_camelCase` |
| `private static` fields | `s_camelCase` |
| `[ThreadStatic]` fields | `t_camelCase` |
| Constants | `PascalCase` |
| All other members | `PascalCase` |

* **Never** qualify with `this.` unless strictly necessary to resolve ambiguity.
* Declare accessibility modifiers **explicitly** on every type and member.
* Use the **narrowest possible scope** — prefer `private` over `internal` over
  `public`.
* Mark members `static` when they do not access instance state.

## Formatting and Line Length

### Expression-bodied members

Use expression bodies (`=>`) for single-expression methods and read-only
properties. When the **total line length would exceed 60 characters**, wrap by
placing the `=>` on the next line, indented:

```csharp
// Short — fits on one line
internal int BorderWidth => _borderWidth;

// Long — wrap the arrow to the next line
private bool IsValidSize(Size size)
    => size.Width > 0 && size.Height > 0;

internal string QualifiedName
    => $"{Namespace}.{TypeName}";
```

> **Important semantic distinction:** `public Foo Bar => new Foo();` creates a
> new instance on every access. `public Foo Bar { get; } = new Foo();` creates
> one instance at construction. Never convert between these forms unless the
> original semantics were provably wrong.

### Braces and blocks

* **Allman style** — opening brace on its own line.
* Insert an **empty line** after closing braces of control-flow blocks and
  **before `return` statements**.
* If a comment precedes a line that needs an empty line above it, the empty line
  goes **before the comment**.

### Ternary operator

Put each branch on its own line unless the whole expression is very short:

```csharp
Color textColor = e.Item.Enabled
    ? GetDarkModeColor(e.TextColor)
    : GetDarkModeColor(SystemColors.GrayText);
```

## Pattern Matching and Switch Expressions

Prefer `switch` expressions over `switch` statements over `if`-chains:

```csharp
string result = value switch
{
    > 0 => "Positive",
    < 0 => "Negative",
    _ => "Zero"
};
```

Use `and`, `or`, relational, property, tuple, type, and list patterns where they
improve clarity. When converting `if`-chains that return or assign, a switch
expression is almost always clearer.

## Readability

1. **Never sacrifice readability for brevity**

Prefer extension method call syntax over static helpers when the same operation is available in both forms — extensions read more naturally and reduce visual noise:

```csharp
// Prefer
Size deviceSize = image.Size.LogicalToDeviceUnits();

// Over
Size deviceSize = DpiHelper.LogicalToDeviceUnits(image.Size);
```

2. **Prefer inline `#pragma` or `[SuppressMessage]`**

Use inline `#pragma` or `[SuppressMessage]` at the call site over global suppressions, so justification is visible in context.

3. **Named arguments**

Use named arguments when passing multiple literals or when the meaning of a parameter isn't clear from the argument expression itself:

```csharp
// GOOD — named arguments clarify meaning of literals
var errorControl = CreateErrorControlForMessage(
    message: "An unexpected error occurred. Please try again.",
    showRetryButton: true);
```

**Note:** When method calls take a lot of space due to a long argument list, consider wrapping the individual arguments on separate lines. If you then decide to use named arguments, use them for *every* argument to improve readability and consistency:

```csharp
LongMethodWithManyNamedArguments(
    firstArgument: value1,
    secondArgument: value2,
    thirdArgument: value3,
    fourthArgument: value4);
```

4. **Wrap dot-chains with more than 2 member accesses** — each call goes on its
   own indented line:

```csharp
// Fine — 2 or fewer:
var names = items.Where(x => x.IsActive).ToList();

// Wrap — more than 2:
var results = collection
    .Where(x => x.IsActive)
    .OrderBy(x => x.Name)
    .Select(x => x.Id)
    .ToList();
```

## Error Handling and Argument Validation

Use **throw-helper methods** — never hand-roll null / range checks:

```csharp
ArgumentNullException.ThrowIfNull(parameter);
ArgumentOutOfRangeException.ThrowIfNegative(value);
ObjectDisposedException.ThrowIf(_disposed, this);
```

Always use `nameof()` for parameter and member names in exceptions and asserts.

## Performance Idioms

* Single-`char` overloads: `text.Contains('c')`, `sb.Append('x')`.
* `ReadOnlySpan<char>` over `Substring` when possible.
* `items.Any()` over `Count() > 0`.
* `TryGetValue` over `ContainsKey` + indexer.
* `string.IsNullOrEmpty` over `?.Length == 0`.
* `Array.Empty<T>()` over `new T[0]`.
* Prefer `using` declarations (`using var ...`) over `using` blocks. Use the
  block form only when a tighter scope is required.

```csharp
using Pen focusPen = new(focusColor)
{
    Width = 1.0f,
    DashStyle = DashStyle.Dot
};
```

## Magic Numbers

Replace/avoid hard-coded literals with named constants or enums for new code when possible. If a literal is truly self-explanatory and unlikely to change, it may be acceptable to leave it as-is.

```csharp

## XML Documentation

Every class, struct, record, interface, and enum — **regardless of access
modifier, including `private` nested types** — must have an XML doc header:

* **`<summary>`** — always present; a concise statement of the type's purpose.
* **`<remarks>`** — add for non-trivial types. Use `<para>` for multiple
  paragraphs.
* Use `<inheritdoc/>` on overridden members.
* Do **not** XML-comment local functions; use a regular `//` comment if
  the purpose is not self-evident.
* Use **Unicode characters** in docs — never HTML entities.
* Indent XML structure with **1 space** per nesting level:

```csharp
/// <summary>
///  Gets or sets the border width of the control.
/// </summary>
/// <remarks>
///  <para>
///   The border width affects the visual appearance and layout
///   calculations of the control.
///  </para>
///  <para>
///   Values must be non-negative. A value of 0 means no border.
///  </para>
/// </remarks>
public int BorderWidth { get; set; }
```

## File Structure

* File-scoped namespaces.
* UTF-8 with BOM, CRLF line endings.
* 4-space indentation, no tabs.
* No trailing whitespace; final newline at end of file.

## WinForms-Specific

### Events

```csharp
public event EventHandler<EventArgs>? Click;

protected virtual void OnClick(EventArgs e)
{
    Click?.Invoke(this, e);
}

// NRT-aware handler signature
private void OnSomeEvent(object? sender, EventArgs e) { }
```

Use `EventArgs.Empty` for parameterless event raises.

### Designer integration

* Mark designer-generated controls as nullable:
  `private Button? _okButton;`
* Dispose components with `is not null`:

```csharp
protected override void Dispose(bool disposing)
{
    if (disposing && components is not null)
    {
        components.Dispose();
    }

    base.Dispose(disposing);
}
```

### Platform attributes

```csharp
[SupportedOSPlatform("windows")]
private void WindowsSpecificMethod() { }
```

Wersje

RepozytoriumWynikLicencja
Ta strona · dotnet/winforms100MIT
zereight/gitlab-mcp100MIT
shinpr/ai-coding-project-boilerplate100MIT
adelrodriguez/skills100MIT
nokri-mohammed/claude-team100MIT
MARUCIE/openclaw-foundry100MIT
kid-sid/codex-spellbook100MIT
shinpr/ai-coding-project-boilerplate96MIT
affaan-m/ECC95MIT

Migawka bazy z 13.11.2026 · wersja paczki d1fbfb45cc4d (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 95csharp-style
    Stosuje konwencje C# przy pisaniu, przeglądzie i refaktoryzacji plików .cs, w tym dokumentację XML i wzorce Unity.
  • 100go-coding-standards
    Podaje standardy i konwencje stylu Go oparte na Effective Go i Go Code Review Comments: kolejność importów, deklaracje zmiennych, inicjalizacja struktur, zagnieżdżenia, receivery, tagi struktur i formatowanie.
  • 100csharp-conventions
    Stosuje ogólne konwencje kodowania w C# 13: nullable reference types, nazewnictwo, formatowanie, obsługę wyjątków, strukturę projektu, dostęp do danych, walidację i logowanie strukturalne.
  • 100code-standards
    Opisuje standardy C# w projekcie Unity: nazewnictwo, kolejność składowych, formatowanie, nullable reference types, zasady pamięci i GC, wzorce testów oraz standardy PR.
  • 95python-style
    Stosuje konwencje kodu Pythona przy pisaniu i przeglądzie: docstringi, adnotacje, nazewnictwo i importy.
  • 93download-sdk
    Prowadzi przez pobieranie i instalację podglądowych runtime .NET wymaganych przez repozytorium WinForms.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.