| Severity | Warning |
| Reported by | Metalama.Framework |
| 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 '<Member>' is passed as an 'out' argument here, which writes it. Pass a local instead, and assign the member in a constructor. |
Cause
Aspects, fabrics and validators must be written in an immutable style, because Metalama can share one instance among several threads and several compilations. A type is subject to this rule when it carries the [ImmutableType] attribute or when it derives from, or implements, a type that requires immutability, such as IAspect or Fabric.
An out argument is a write, but it doesn't look like an assignment, so it is easy to miss. Metalama reports LAMA0888 when an instance field or automatic property of such a type is passed as an out argument, for example int.TryParse( text, out this._value ), outside a constructor or an init accessor of the declaring type. In the message, <Type> is the type that must be immutable and <Member> is the name of the field or property that is passed.
An out argument in a constructor is part of the construction and isn't reported. The analyzer doesn't report ref arguments either, because the called method can only read the value, as Volatile.Read does. A direct assignment is reported by LAMA0887.
This diagnostic is reported by a Roslyn analyzer, and snapshot tests of aspects don't run analyzers, so this article has no example.
Resolution
Pass a local variable as the out argument, and assign the member from the local variable in a constructor. If the value must change after construction, don't keep it in the aspect, fabric or validator.