К основному содержанию
правило

c-sharp — правило для Cursor: что делает и как установить

Задаёт правила оформления кода на C# для Cursor: от стиля Allman и именования сущностей до внедрения зависимостей и запрета блокирующих асинхронных вызовов.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/c-sharp.mdc
Открыть на GitHub

Что делает c-sharp

Правило определяет стандарты разработки на .NET для проектов в Cursor. Оно задаёт именование типов в PascalCase, интерфейсов с префиксом I, полей с подчёркивания _camelCase и суффикс Async для асинхронных методов. Для отступов используются четыре пробела. Все открывающие фигурные скобки выносятся на новую строку по стилю Allman.

Инструкция направляет модель к современному синтаксису C#. В коде поощряются сопоставление с шаблонами и неизменяемые типы record. Архитектурный блок требует явного внедрения через конструктор. Прямая инициализация зависимостей и паттерн Service Locator строго запрещены.

Конфигурация нацелена на шаблон **/*. Поэтому Cursor применяет ограничения ко всем файлам проекта. Правило пресекает сборку строк через + внутри циклов и метод async void вне событий UI. Блокирующие вызовы вроде .Wait() для асинхронных операций не допускаются.

Какие задачи решает

  • Привести оформление кода на C# к стилю Allman с фигурными скобками на отдельной строке
  • Настроить именование сущностей .NET с префиксами для интерфейсов и приватных полей
  • Перевести модели данных на неизменяемые record и свойства с модификатором init
  • Исключить блокирующие вызовы асинхронного кода вроде .Wait()

Примеры запросов агенту

  • Сделай сервис OrderService с внедрением репозитория через конструктор
  • Напиши неизменяемую модель пользователя и DTO для передачи данных через record
  • Оптимизируй цикл сборки текстового отчёта через StringBuilder

Как установить c-sharp

Вручную: положить файлы

.cursor/rules/c-sharp.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о c-sharp

Как установить правило c-sharp в Cursor?

Создайте файл по пути .cursor/rules/c-sharp.mdc в корне репозитория и сохраните туда содержимое правила.

Зачем нужно правило c-sharp?

Оно заставляет Cursor генерировать C#-код по конвенциям .NET: с единым именованием, скобками Allman, внедрением зависимостей и без антипаттернов в асинхронном коде.

Какие требования к асинхронному коду задаёт это правило?

Правило запрещает использовать .Wait() и методы async void, за исключением обработчиков событий вроде Button_Click. Все асинхронные операции должны возвращать Task или Task<T> и именоваться с суффиксом Async.

Исходный текст

c-sharp.mdc · CC0-1.0
---
description: This guide defines definitive C# coding standards and best practices for our team, covering naming, formatting, modern language features, performance, security, and error handling to ensure consistent, maintainable, and high-quality code.
globs: **/*
---
# c-sharp Best Practices

This document outlines the definitive C# coding standards and best practices for our team. Adhering to these guidelines ensures consistency, readability, maintainability, and high performance across all our C# projects.

## Code Organization and Structure

### 1. Naming Conventions
Always follow standard .NET naming conventions to improve readability and predictability.

*   **Types (Classes, Structs, Enums, Delegates, Records):** `PascalCase`
*   **Interfaces:** `IPascalCase`
*   **Methods, Public Properties, Events:** `PascalCase`
*   **Public Constants:** `PascalCase`
*   **Local Variables, Method Parameters:** `camelCase`
*   **Private/Protected Fields:** `_camelCase` (underscore prefix)
*   **Async Methods:** `PascalCase` ending with `Async`

❌ BAD:
```csharp
public class myService {
    private string name;
    public void getdata() { /* ... */ }
    public async Task do_work() { /* ... */ }
    public interface IMyServiceImplementation { /* ... */ } // Incorrect interface naming
}
```

✅ GOOD:
```csharp
public class MyService {
    private readonly ILogger _logger; // Readonly private fields
    private string _name;
    public const int MaxRetries = 3; // Public constants are PascalCase

    public MyService(ILogger logger) {
        _logger = logger;
    }

    public void GetData() { /* ... */ }
    public async Task DoWorkAsync() { /* ... */ }
}
public interface IService { /* ... */ } // Correct interface naming
```

### 2. Formatting
Always maintain consistent code layout for clarity.

*   **Indentation:** Use **4 spaces**. Configure your IDE to use spaces, not tabs.
*   **Braces:** Use [Allman style](https://en.wikipedia.org/wiki/Indent_style#Allman_style) where each brace begins on a new line. Always use braces, even for single-statement blocks.
*   **`using` Directives:** Place at the top of the file, outside the namespace. Sort alphabetically, with `System` namespaces first.
*   **Auto-properties:** Keep on a single line.
*   **Generic Constraints:** Place on separate, indented lines.

❌ BAD:
```csharp
using System.Collections.Generic;
using System;
namespace MyNamespace {
class MyClass {
    public int Age {get;set;}
    void DoSomething() {
        if(true)
            Console.WriteLine("Hello");
    }
}}
```

✅ GOOD:
```csharp
using System;
using System.Collections.Generic;

namespace MyNamespace
{
    public class MyClass
    {
        public int Age { get; set; }

        public void DoSomething()
        {
            if (true)
            {
                Console.WriteLine("Hello");
            }
        }
    }
}
```

### 3. Modern Language Features
Always embrace modern C# features for cleaner, more concise, and safer code.

*   **`var` Keyword:** Use `var` when the type is obvious from the right-hand side of the assignment. Avoid `var` when the type is not immediately clear.
*   **Expression-bodied Members:** Use for single-expression methods, properties, and accessors.
*   **Object/Collection Initializers:** Prefer for creating and populating objects/collections.
*   **Pattern Matching:** Use for type checks and value comparisons.
*   **Nullable Reference Types:** Enable and address warnings (`#nullable enable`).
*   **Records:** Use for immutable data transfer objects (DTOs) or value-based types.

❌ BAD:
```csharp
string name = "John Doe";
public int GetCount() { return _items.Count; }
MyObject obj = new MyObject();
obj.Property1 = "Value1";
obj.Property2 = 123;
if (item is string) { Console.WriteLine((string)item); }
```

✅ GOOD:
```csharp
var name = "John Doe"; // Type is obvious
public int Count => _items.Count; // Expression-bodied property
public void Log(string message) => _logger.LogInformation(message); // Expression-bodied method

var obj = new MyObject {
    Property1 = "Value1",
    Property2 = 123
};

if (item is string s) { Console.WriteLine(s); } // Pattern matching
```

## Common Patterns and Anti-patterns

### 1. Dependency Injection (DI)
Always use constructor injection for dependencies. Never use service locators or direct instantiation of dependencies within classes.

❌ BAD:
```csharp
public class MyService
{
    private readonly IRepository _repository = new ConcreteRepository(); // Direct instantiation
    // Or: private readonly IRepository _repository = ServiceLocator.Resolve<IRepository>();
}
```

✅ GOOD:
```csharp
public class MyService
{
    private readonly IRepository _repository;

    public MyService(IRepository repository) // Constructor injection
    {
        _repository = repository;
    }
}
```

### 2. Immutability
Favor immutable objects, especially for DTOs and shared state, to reduce side effects and improve thread safety. Use `record` types or `init` accessors.

❌ BAD:
```csharp
public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
```

✅ GOOD:
```csharp
public record User(string FirstName, string LastName); // Immutable record

// Or for classes:
public class Product
{
    public int Id { get; init; } // Init-only setter
    public string Name { get; init; }
}
```

## Performance Considerations

### 1. Asynchronous Programming
Always use `async/await` for I/O-bound operations to prevent blocking threads. Avoid `async void` methods (except for event handlers) and blocking `async` calls.

❌ BAD:
```csharp
public void DoWork() {
    SomeAsyncOperation().Wait(); // Blocks the thread
}
public async void Event_Click(object sender, EventArgs e) { /* ... */ } // Async void outside event handlers
```

✅ GOOD:
```csharp
public async Task DoWorkAsync() {
    await SomeAsyncOperation(); // Awaits without blocking
}
// For event handlers, async void is acceptable
public async void Button_Click(object sender, EventArgs e) {
    await LoadDataAsync();
}
```

### 2. String Manipulation
Always use `StringBuilder` for concatenating many strings in loops.

❌ BAD:
```csharp
string result = "";
for (int i = 0; i < 1000; i++) {
    result += i.ToString(); // Inefficient in a loop, creates many new strings
}
```

✅ GOOD:
```csharp
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.Append(i);
}
string result = sb.ToString();
```

## Common Pitfalls and Gotchas

### 1. Magic Strings/Numbers
Never hardcode string literals or numeric values directly in code. Always use constants or configuration.

❌ BAD:
```csharp
public void ProcessOrder(string status) {
    if (status == "Pending") { /* ... */ }
}
public decimal CalculateDiscount(decimal price) {
    return price * 0.10m;
}
```

✅ GOOD:
```csharp
public static class OrderStatus {
    public const string Pending = "Pending";
    public const string Completed = "Completed";
}
public const decimal DiscountRate = 0.10m;

public void ProcessOrder(string status) {
    if (status == OrderStatus.Pending) { /* ... */ }
}
public decimal CalculateDiscount(decimal price) {
    return price * DiscountRate;
}
```

### 2. Deep Nesting
Always refactor deeply nested `if`/`for` blocks to improve readability. Use guard clauses or extract methods.

❌ BAD:
```csharp
if (condition1) {
    if (condition2) {
        if (condition3) {
            // ... complex logic
        }
    }
}
```

✅ GOOD:
```csharp
if (!condition1) return;
if (!condition2) return;
if (!condition3) return;
// ... simplified logic
```

## Security Best Practices

### 1. Input Validation
Always validate all external input (user input, API calls, file contents) at the boundaries of your application.

❌ BAD:
```csharp
public void CreateUser(string username, string password) {
    // Directly use inputs without validation
    _userRepository.Add(new User(username, password));
}
```

✅ GOOD:
```csharp
public void CreateUser(string username, string password) {
    if (string.IsNullOrWhiteSpace(username) || username.Length < 5) {
        throw new ArgumentException("Invalid username.");
    }
    // ... more validation (e.g., password strength, SQL injection prevention)
    _userRepository.Add(new User(username, password));
}
```

### 2. Secure Data Handling
Never store sensitive information (passwords, API keys) in plain text. Always use secure configuration, environment variables, or secrets management solutions.

## Error Handling

### 1. Specific Exceptions
Always catch specific exceptions rather than general `Exception`. Log and rethrow when appropriate.

❌ BAD:
```csharp
try {
    // ...
} catch (Exception ex) { // Too broad, hides specific issues
    _logger.LogError(ex, "An error occurred.");
    throw; // Rethrows original exception, losing stack trace if not careful
}
```

✅ GOOD:
```csharp
try {
    // ...
} catch (FileNotFoundException ex) {
    _logger.LogError(ex, "File not found at path {Path}.", _filePath);
    // Specific handling, e.g., notify user
} catch (IOException ex) {
    _logger.LogError(ex, "An I/O error occurred during file operation.");
    throw; // Rethrow if caller needs to handle, preserving stack trace
}
```

### 2. `using` for `IDisposable`
Always use the `using` statement for objects that implement `IDisposable` to ensure proper resource cleanup.

❌ BAD:
```csharp
SqlConnection connection = new SqlConnection("...");
connection.Open();
// ... forgot to close/dispose
```

✅ GOOD:
```csharp
using (var connection = new SqlConnection("..."))
{
    connection.Open();
    // ...
} // Connection is automatically disposed here
```

## API Design

### 1. Clear Contracts
Always define clear, well-documented API contracts using DTOs and interfaces. Avoid exposing internal implementation details.

### 2. Asynchronous APIs
Always expose `async` methods for any I/O-bound operations in public APIs.

❌ BAD:
```csharp
public IEnumerable<Product> GetProducts() { /* Sync I/O operations */ }
```

✅ GOOD:
```csharp
public Task<IEnumerable<Product>> GetProductsAsync() { /* Async I/O operations */ }
```

## Testing Approaches

### 1. Unit Testing
Always write focused unit tests for individual components, mocking external dependencies.

### 2. Dependency Injection for Testability
Always design classes with Dependency Injection to make them easily testable.

❌ BAD:
```csharp
public class OrderProcessor {
    private readonly PaymentGateway _gateway = new PaymentGateway(); // Hard dependency
    public void Process(Order order) { _gateway.Charge(order.Amount); }
}
```

✅ GOOD:
```csharp
public interface IPaymentGateway { void Charge(decimal amount); }
public class PaymentGateway : IPaymentGateway { /* ... */ }

public class OrderProcessor {
    private readonly IPaymentGateway _gateway;
    public OrderProcessor(IPaymentGateway gateway) { _gateway = gateway; }
    public void Process(Order order) { _gateway.Charge(order.Amount); }
}
// Now IPaymentGateway can be easily mocked in tests.
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Языки программирования» →
c-sharp-pro davila7 Субагент генерирует и рефакторит код на C# 12 и 13 с учётом стандартов .NET, EF Core и ASP.NET Core. Пригодится при проектировании API, миграции архитектуры и настройке тестов. 1 016установок unity-vrc-udon-sharp niaka3dayo Скилл для написания, разбора и отладки UdonSharp C# под VRChat SDK 3.10.5. Держит под рукой ограничения Udon и правила сетевой синхронизации. CX Codex +1 1 000установок dotnet-design-pattern-review официальный github Проверяет выбранный C#/.NET-код на применение паттернов проектирования и предлагает правки без изменения файлов. Подходит для ревью архитектуры проекта. 11 609установок analyzing-dotnet-performance dotnet Ищет около 50 антипаттернов производительности в коде на C# и .NET — от лишних аллокаций в строках до блокировок в async. Пригодится при аудите горячих путей перед релизом. CX Codex +1 4 900установок csharp-developer https://github.com/Jeffallan Настраивает правила разработки на .NET 8 и C# 12 для создания API, Blazor-приложений и работы с EF Core. Пригодится при проектировании сервисов с CQRS и Result pattern. CX Codex +1 4 800установок dotnet-core-expert https://github.com/Jeffallan Скилл для Claude Code, который ведёт агента по сборке бэкенда на .NET 8: минимальные API, чистая архитектура, EF Core, CQRS и JWT, от требований до dotnet test. CX Codex +1 4 700установок

Из того же набора240

Весь набор →
clerk Правило для Cursor задаёт жёсткие требования к аутентификации Clerk: PKCE, серверные проверки, короткие токены. Пригодится, когда в проекте уже есть Clerk и нужен порядок в безопасности. ★ 3 580звёзд репо circleci Задаёт стандарты оформления пайплайнов CircleCI в проекте. Помогает генерировать надёжные конфигурации с кэшированием, reusable-командами и параллельными тестами. ★ 3 580звёзд репо cheerio Правило задаёт практики для cheerio в Node.js: структура скрейперов, выбор селекторов, очистка данных и тесты. ★ 3 580звёзд репо chakra-ui Правило для Cursor задаёт, как писать интерфейсы на Chakra UI v2: тема через токены, варианты компонентов через рецепты, стилевые пропсы вместо CSS. ★ 3 580звёзд репо bun Правило задаёт стиль JavaScript-кода в файлах .js и .jsx: предлагает использовать инструменты Bun, современные конструкции языка и понятную структуру проекта. ★ 3 580звёзд репо bottle Правило для Cursor задаёт структуру Bottle-проекта: модули вместо одного app.py, конфиг через app.config, валидация Pydantic. Пригодится, если пишете бэкенд на Bottle. ★ 3 580звёзд репо boto3 Направляет ассистента писать надёжный код на Python с boto3: переиспользовать клиенты, разбивать запросы на пачки и выбирать готовые пагинаторы вместо ручных циклов. ★ 3 580звёзд репо black Правило для Cursor задаёт единый стиль Python-кода с помощью Black. Оно помогает согласовать форматирование исходников и проверять его перед слиянием изменений. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой