Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions _rules/1030.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
rule_id: 1030
rule_category: class-design
title: Know when to use a record and when to use a class
severity: 2
---
Records and classes serve different purposes. Choosing the right one keeps the intent of your type clear. This rule focuses on `record` (record class) vs `class`; for value types, consider `struct` or `record struct` instead.

Use a **record** when:
- The type represents data, not behavior (e.g. a DTO, a value object, or a response model).
- Structural equality (compare by value, not by reference) is the correct semantics.
Comment thread
dennisdoomen marked this conversation as resolved.
- Immutability is desired (use `init`-only properties).

```csharp
public record OrderSummary(Guid OrderId, decimal TotalAmount, DateTimeOffset CreatedAt);
```

**Note:** Record equality is shallow. If a record property is a collection (e.g. `List<T>` or an array), `Equals` and `GetHashCode` will not compare the contents, which can lead to subtle bugs.

Use a **record struct** when the same criteria apply, but you also want value-type semantics: stack allocation, no null, and copy-on-assignment. This is appropriate for small, frequently passed immutable data such as coordinates, colors, or date ranges. Avoid mutable `record struct` — mutations on a copy don't affect the original, which leads to confusing bugs.

Use a **class** when:
- The type has mutable state or significant behavior.
- Identity matters (two instances with the same data are not necessarily equal).
- The type manages a lifecycle (e.g. implements `IDisposable`).

```csharp
public class OrderProcessor
{
public void Process(Order order) { ... }
}
```

Mixing both in one type (e.g. a record with complex behavior and mutable state) is a sign of a design problem.