Open sandboxFocusImprove this doc

COM017: Different Relationship Attributes on a Property and Its Backing Field

Severity Warning
Reported by PostSharp.Patterns.Aggregation
Message The backing field of the automatic property <Property> is annotated with [<FieldAttribute>] and the property with [<PropertyAttribute>]. The relationship is [<PropertyAttribute>]; the attribute of the backing field does not change it.

Cause

The AggregatableAttribute aspect reads the relationship of an automatic property from the attributes of the property. PostSharp reports COM017 when the property has one relationship attribute, such as ReferenceAttribute, and the field: target applies another one, such as ChildAttribute, to its backing field. The attribute of the property wins, so the two attributes contradict each other and one of them is not what you meant.

In the following example, the Customer property is a reference, although its backing field has [Child]: the customer gets no parent.

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

namespace Errors.COM017_Error;

[Aggregatable]
public class Order
{
    // The property says [Reference], so [field: Child] does not make the customer a child.
    [Reference] [field: Child] public Customer? Customer { get; set; }
}

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

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

        object? parent = Post.Cast<Customer, IAggregatable>( order.Customer ).Parent;
        Console.WriteLine( $"{order.Customer.Name}, parent of the customer: {parent ?? "none"}" );
    }
}
warning COM017: COM017_Error.cs(11,49): The backing field of the automatic property Errors.COM017_Error.Order.Customer is annotated with [Child] and the property with [Reference]. The relationship is [Reference]; the attribute of the backing field does not change it.

Resolution

Decide which relationship the property has, and apply only that attribute, to the property:

  • If the attribute of the property is right, remove the attribute of the backing field.
  • Otherwise, replace the attribute of the property with the one of the backing field, and remove the field: attribute.

In the following example, the customer is shared by several orders, so the property keeps [Reference] only.

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

namespace Errors.COM017_Fixed;

[Aggregatable]
public class Order
{
    // One attribute, on the property, states the relationship.
    [Reference] public Customer? Customer { get; set; }
}

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

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

        object? parent = Post.Cast<Customer, IAggregatable>( order.Customer ).Parent;
        Console.WriteLine( $"{order.Customer.Name}, parent of the customer: {parent ?? "none"}" );
    }
}
Alice, parent of the customer: none

See Also

Reference

AggregatableAttribute
ChildAttribute
ReferenceAttribute

Other Resources

Annotating an Object Model for Parent/Child Relationships (Aggregatable)