Open sandboxFocus

Class ImmutableTypeAttribute

Declares that a type must be written in an immutable style, and requires every type that derives from it or implements it to be written that way too. An analyzer verifies the declaration and reports a warning when it does not hold.

Inheritance
ImmutableTypeAttribute
Namespace: Metalama.Framework.Utilities
Assembly: Metalama.Framework.dll
Syntax
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Interface, Inherited = false)]
public sealed class ImmutableTypeAttribute : Attribute
Remarks

An aspect is instantiated once and reused for every target it applies to, and at design time across compilations. State kept on it therefore leaks from one target to the next, in an order the author does not control. That is why IAspect and Fabric carry this attribute, and why every aspect, fabric and validator is checked.

Concretely, in a type subject to this contract:

  • every instance field must be readonly, or private and assigned only in a constructor or an init accessor;
  • every automatically implemented property must have no setter, an init accessor, or a private setter assigned only in a constructor or an init accessor;
  • and the type of every such member must itself be immutable, all the way down.

A member whose write access is private is checked at its assignments rather than at its declaration, because private write access confines every assignment to the declaring type, so the analyzer can see all of them. Passing such a member as a ref or out argument counts as an assignment.

Intrinsic types, delegates, enumerations and the immutable collections are immutable, and an immutable collection is immutable only when its type arguments are. A type that is not marked with this attribute and is not otherwise known to the analyzer is not immutable, so marking a type propagates the obligation to the types of all of its members.

This attribute is deliberately not System.ComponentModel.ImmutableObjectAttribute. That one exists to tell a designer that an object has no editable sub-properties, it is applied in the wild for that reason, and it says nothing about this contract. Reusing it would mean checking code whose author never opted in. The name also avoids Metalama.Patterns.Immutability.ImmutableAttribute, which is a different feature and may be imported in the same file.

There is deliberately no per-type waiver. Where the contract is genuinely not wanted on one declaration, the ordinary suppression mechanisms apply: #pragma warning disable, [SuppressMessage] with a justification, or a severity in an .editorconfig. A project that implements the framework itself, rather than using it, sets the MetalamaEnforceImmutabilityContract MSBuild property to false to turn the contract off entirely.

Constructors

Name Description
ImmutableTypeAttribute()

Extension Methods

See Also