Open sandboxFocusImprove this doc

COM016: Reference Attribute Only on the Backing Field of a Read-Only Property

Severity Warning
Reported by PostSharp.Patterns.Aggregation
Message The [Reference] attribute applied to the backing field of the read-only automatic property <Property> does not set the relationship of the property: it only excludes the field from the immutability analysis of the type <DeclaringType>. Apply [Reference] to the property as well, or set the <MSBuildProperty> MSBuild property to True to read the annotations of an automatic property and of its backing field as one.

Cause

The backing field of a read-only automatic property is a readonly field. A ReferenceAttribute on a readonly field has a meaning of its own: it excludes the field from the analysis that decides whether the type is immutable, which the threading models use. The relationship of the property, however, is read from the attributes of the property, not from those of its backing field.

PostSharp reports COM016 when the field: target applies [Reference] to the backing field of a read-only automatic property, and the property itself has no relationship attribute. The attribute then excludes the field from the immutability analysis of <DeclaringType>, but does not make the property a reference. <MSBuildProperty> is PostSharpUnifiedAutomaticPropertyAnnotations.

In the following example, the Customer property of a [Synchronized] class has [Reference] on its backing field only.

using System;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Threading;

namespace Errors.COM016_Error;

[Synchronized]
public class Order
{
    // The attribute excludes the backing field from the immutability analysis, but the property has no relationship attribute.
    [field: Reference] public Customer Customer { get; } = new Customer();
}

public class Customer
{
    public string Name { get; set; } = "Alice";
}

public static class Program
{
    public static void Main()
    {
        Order order = new Order();

        Console.WriteLine( $"Customer: {order.Customer.Name}" );
    }
}
warning COM016: COM016_Error.cs(11,40): The [Reference] attribute applied to the backing field of the read-only automatic property Errors.COM016_Error.Order.Customer does not set the relationship of the property: it only excludes the field from the immutability analysis of the type Errors.COM016_Error.Order. Apply [Reference] to the property as well, or set the PostSharpUnifiedAutomaticPropertyAnnotations MSBuild property to True to read the annotations of an automatic property and of its backing field as one.

Resolution

  • Apply [Reference] to the property too, and keep it on the backing field if the field must stay excluded from the immutability analysis. PostSharp does not report the redundancy in this case, because both attributes have an effect.
  • Alternatively, set the PostSharpUnifiedAutomaticPropertyAnnotations MSBuild property to True in the project. PostSharp then reads the attributes of an automatic property and of its backing field as one set, and [Reference] on the property alone has both effects.

In the following example, [Reference] is on both the property and its backing field.

using System;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Threading;

namespace Errors.COM016_Fixed;

[Synchronized]
public class Order
{
    // [Reference] on the property sets the relationship; on the backing field, it excludes the field from the immutability analysis.
    [Reference] [field: Reference] public Customer Customer { get; } = new Customer();
}

public class Customer
{
    public string Name { get; set; } = "Alice";
}

public static class Program
{
    public static void Main()
    {
        Order order = new Order();

        Console.WriteLine( $"Customer: {order.Customer.Name}" );
    }
}
Customer: Alice

See Also

Reference

ReferenceAttribute
SynchronizedAttribute

Other Resources

Annotating an Object Model for Parent/Child Relationships (Aggregatable)
Writing Thread-Safe Code with Threading Models