Skip to content

Add immutability assertions and filters for types #329

@vbreuss

Description

@vbreuss

Why

Immutability is a deliberate design property: value objects, DTOs, messages, and event types are often required to be immutable so they can be shared freely across threads and cached safely. Today this convention can only be approximated by combining several member-level checks (readonly fields, properties without setters), which is verbose and easy to get subtly wrong (e.g. forgetting init-only setters or non-public members).

A dedicated assertion makes the intent explicit and keeps the rule in one place:

await Expect.That(In.AssemblyContaining<MyEvent>()
        .Types().WhichAreClasses().WithName("*Event").AsWildcard())
    .AreImmutable();

Proposal

  • Assertions: ThatType.IsImmutable() / IsNotImmutable() and ThatTypes.AreImmutable() / AreNotImmutable()
  • Filter: Filtered.Types.WhichAreImmutable() / WhichAreNotImmutable()

A type counts as immutable when all instance fields are readonly and all instance properties have no setter (or only an init setter). The failure message should name the mutable members, so violations are immediately actionable.

Open question

Should init setters count as immutable? Suggestion: yes by default, with an option to be strict.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions