Open sandboxFocusImprove this doc

LAMA0884: A member of an immutable type is an interface that isn't marked immutable

Severity Warning
Reported by Metalama.Framework (Roslyn analyzer)
Message '<Type>' must be written in an immutable style because it is an aspect, a fabric, a validator, or another type bound by the [ImmutableType] contract, but '<InterfaceType>' is not marked [ImmutableType]. Marking it requires every implementation to be immutable, which this analyzer verifies. Path: <Path>.

Cause

Aspects, fabrics, validators, and the types that you mark with the [ImmutableType] attribute must be written in an immutable style, because an aspect instance is reused for all its targets. See LAMA0882 for the rationale and for the rules that decide whether a type is immutable.

LAMA0884 is the variant of LAMA0882 for a field or automatic property whose type, <InterfaceType>, is an interface or an abstract class that isn't marked with [ImmutableType] and that the analyzer doesn't know. A typical example is a field of type IEnumerable<string> or IReadOnlyList<string>: the interface doesn't prevent the underlying object from being a List<string> that someone modifies later.

The analyzer reports a separate diagnostic because the remedy is different. An interface has no members to verify, so marking it with [ImmutableType] doesn't check anything on the interface itself. It instead requires every type that implements the interface to be written in an immutable style, and the analyzer verifies each implementation in turn. This guarantee reaches only the implementations that are compiled with the analyzer, so you may decide to weigh this rule differently from the others, for instance by changing its severity in an .editorconfig file.

<Path> shows the chain from <Type> to <InterfaceType>, for example ReportAspect -> _lines -> IEnumerable<string> (an interface or abstract type that is not marked [ImmutableType]).

This diagnostic is reported by a Roslyn analyzer, which doesn't run in the snapshot tests of this documentation, so it can't be shown in an example.

Resolution

  • Replace the interface with a concrete immutable type, such as ImmutableArray<string> instead of IEnumerable<string> or IReadOnlyList<string>.
  • If the interface is yours, mark it with [ImmutableType]. Every implementation must then be immutable, and the analyzer reports the implementations that aren't, with LAMA0880, LAMA0881 or LAMA0882.
  • If the interface isn't yours and you know that every value you store in it is immutable, declare it with a MetalamaImmutableType item in the project file (see LAMA0885).
  • If the warning is unwanted, lower its severity in an .editorconfig file, or suppress it with #pragma warning disable LAMA0884.

See also