用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-csharp-api-design命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
AI-powered wiki generation for code repositories with commands, agents, and skills
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
Skill manifest management for dotnet-agent-harness. Tracks skill dependencies, conflicts, version compatibility, and provides validation and resolution tools. Triggers on: skill manifest, dependency resolution, skill compatibility, version conflicts, build manifest, validate dependencies.
基于 SOC 职业分类
正在显示 SKILL.md
| name | dotnet-csharp-api-design |
| description | Designs public .NET APIs. Naming, parameter ordering, return types, error patterns, extensions. |
| metadata | {"short-description":".NET skill guidance for api tasks"} |
Design-time principles for creating public .NET APIs that are intuitive, consistent, and forward-compatible. Covers naming conventions for API surface, parameter ordering, return type selection, error reporting strategies, extension points, and wire compatibility for serialized types. This skill addresses the design decisions that make APIs compatible and usable in the first place, before enforcement tooling gets involved.
Version assumptions: .NET 8.0+ baseline. Examples use modern C# features (primary constructors, collection expressions) where appropriate.
Cross-references: [skill:dotnet-library-api-compat] for compatibility enforcement, [skill:dotnet-api-surface-validation] for CI detection, [skill:dotnet-csharp-coding-standards] for general naming rules, [skill:dotnet-api-versioning] for HTTP API versioning, [skill:dotnet-nuget-authoring] for SemVer and packaging.
Follow the .NET Framework Design Guidelines naming patterns for public API types:
| Type Kind | Suffix Pattern | Example |
|---|---|---|
| Base class | Base suffix only for abstract base types | ValidatorBase |
| Interface | I prefix | IWidgetFactory |
| Exception | Exception suffix | WidgetNotFoundException |
| Attribute | Attribute suffix | RequiredPermissionAttribute |
| Event args | EventArgs suffix | WidgetCreatedEventArgs |
| Options/config | Options suffix | WidgetServiceOptions |
| Builder | Builder suffix | WidgetBuilder |
| Pattern | Convention | Example |
|---|---|---|
| Synchronous | Verb or verb phrase | Calculate(), GetWidget() |
| Asynchronous | Async suffix | CalculateAsync(), GetWidgetAsync() |
| Boolean query | Is/Has/Can prefix | IsValid(), HasPermission() |
| Try pattern | Try prefix, out parameter | TryGetWidget(int id, out Widget widget) |
| Factory | Create prefix | CreateWidget(), CreateWidgetAsync() |
| Conversion | To/From prefix | ToDto(), FromEntity() |
Spell out words in public APIs even if internal code uses abbreviations. Public APIs are consumed by developers who may not share the team's domain shorthand:
// WRONG -- abbreviations in public surface
public IReadOnlyList<TxnResult> GetRecentTxns(int cnt);
// CORRECT -- spelled out for clarity
public IReadOnlyList<TransactionResult> GetRecentTransactions(int count);
```text
---
## Parameter Ordering
Consistent parameter ordering reduces cognitive load and enables fluent usage patterns across an API surface.
### Standard Order
1. **Target/subject** -- the primary entity being operated on
2. **Required parameters** -- essential inputs without defaults
3. **Optional parameters** -- inputs with sensible defaults
4. **Cancellation token** -- always last (convention enforced by CA1068)
```csharp
// Consistent ordering across the API surface
public Task<Widget> GetWidgetAsync(
int widgetId, // 1. Target
WidgetOptions options, // 2. Required
bool includeHistory = false, // 3. Optional
CancellationToken cancellationToken = default); // 4. Always last
public Task<Widget> UpdateWidgetAsync(
int widgetId, // 1. Target
WidgetUpdateRequest request, // 2. Required
validateFirst = , // Optional
CancellationToken cancellationToken = );
```text
Design overloads a progression simple to detailed. Each overload should to the next more specific one:
```csharp
=> GetWidgetAsync(widgetId, WidgetOptions.Default, cancellationToken);
;
```text
---
| Scenario | Return Type | Rationale |
| --------------------------------- | -------------------------------------- | ------------------------------------------------ |
| Single entity, always exists | `Widget` | Throw found |
| Single entity, may exist | `Widget?` | Nullable reference type communicates optionality |
| Collection, possibly empty | `IReadOnlyList<Widget>` | Immutable, indexable, communicates no mutation |
| Streaming results | `IAsyncEnumerable<Widget>` | Avoids buffering entire result |
| Operation result detail | `Result<Widget>` / discriminated union | Rich error info without exceptions |
| Void | `Task` | Never ` ` except handlers |
| Frequently synchronous completion | `ValueTask<Widget>` | Avoids Task allocation cache hits |
```csharp
;
;
;
```text
Use the Try pattern operations that have a common, non-exceptional failure mode:
```csharp
;
Task<Widget?> TryGetWidgetAsync( widgetId,
CancellationToken cancellationToken = );
```text
---
Design exception types that enable callers to at the right granularity:
```csharp
:
{
{ }
{ }
}
:
{
WidgetId { ; }
=> WidgetId = widgetId;
}
:
{
IReadOnlyList<> Errors { ; }
=> Errors = errors;
}
```text
| Approach | When to Use |
| ---------------------------- | ------------------------------------------------------------------------- |
| Throw exception | Unexpected failures, programming errors, infrastructure failures |
| Return `` / `` | a normal,
{
ArgumentException.ThrowIfNullOrWhiteSpace(name);
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(price);
Widget(name, price);
}
```text
Use `ArgumentException.ThrowIfNullOrWhiteSpace` (.NET +) `ArgumentOutOfRangeException.ThrowIfNegativeOrZero` (.NET
+) instead of manual checks ` ArgumentNullException(...)`.
{
;
}
{
Func<Widget, CancellationToken, ValueTask>? OnWidgetCreated { ; ; }
}
{
List<IWidgetValidator> _validators = [];
{
_validators.Add(validator);
;
}
{
_validators.Add( DelegateValidator(validator));
;
}
=> (_validators);
}
```text
| Guideline | Rationale |
| ---------------------------------------------------------------------- | ------------------------------------------------------------ |
| Place extensions the same | `` |
| `` `` | |
| | |
| ' `` | `<>` ``; avoids polluting IntelliSense |
---
; old clients ignore field |
| Add member at the end | Existing serialized values map to existing members |
| Rename property `[JsonPropertyName]` annotation | Wire name stays the same |
| Change | Impact |
| --------------------------------------------------- | ------------------------------------------------------------ |
| ; old clients send unrecognized fields |
| Change property type | Deserialization failure silent data loss |
|
{
[]
Id { ; ; }
[]
Name { ; ; }
[]
? Category { ; ; }
[]
[]
Priority { ; ; }
}
```json
```csharp
[]
WidgetStatus
{
Draft,
Active,
Archived
}
WidgetPriority
{
Low = ,
Medium = ,
High =
}
```text
---
Before shipping a API, verify each concern:
**Naming** -- follows .NET naming conventions, no abbreviations, consistent rest of API surface
**Parameters** -- ordered (target, , optional, CancellationToken), no more than ~ parameters (use options
complex APIs)
**Return types** --