| Severity | Warning |
| Reported by | PostSharp.Patterns.Aggregation |
| Message | Field/property <DeclaringType>.<Member> is a collection and must be annotated with the custom attribute [Child] or [Reference]. The member has been assumed to be a reference for backward compatibility. |
Cause
The threading models, such as ThreadUnsafeAttribute or SynchronizedAttribute, add the AggregatableAttribute aspect to their target class, in a compatibility mode. When a field, or an automatic property, can hold either a child or a reference and has no relationship attribute, the [Aggregatable] aspect alone reports the error COM002. In this compatibility mode, PostSharp treats the member as a reference instead, and reports COM014 when the type of the member is a collection, because a collection has no good default.
In the following example, the items field of a [ThreadUnsafe] class is a List<string> without attribute.
using System;
using System.Collections.Generic;
using PostSharp.Patterns.Threading;
namespace Errors.COM014_Error;
[ThreadUnsafe]
public class ShoppingCart
{
// The field is a collection, but it does not say whether it is a child or a reference.
private readonly List<string> items = new List<string>();
public void Add( string item ) => this.items.Add( item );
public string Describe() => string.Join( ", ", this.items );
}
public static class Program
{
public static void Main()
{
ShoppingCart cart = new ShoppingCart();
cart.Add( "Keyboard" );
cart.Add( "Mouse" );
Console.WriteLine( $"Cart: {cart.Describe()}" );
}
}
warning COM014: COM014_Error.cs(11,35): Field/property Errors.COM014_Error.ShoppingCart.items is a collection and must be annotated with the custom attribute [Child] or [Reference]. The member has been assumed to be a reference for backward compatibility.
Resolution
Annotate the member with one of the relationship attributes:
- ReferenceAttribute when the class only refers to the collection or to its items. This keeps the behavior that PostSharp assumed.
- ChildAttribute when the collection and its items belong to the class. A child collection must be an advisable collection, such as AdvisableCollection<T>.
In the following example, the list is a reference.
using System;
using System.Collections.Generic;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Threading;
namespace Errors.COM014_Fixed;
[ThreadUnsafe]
public class ShoppingCart
{
// The list is a plain .NET collection, not a part of the object model: the cart only refers to it.
[Reference]
private readonly List<string> items = new List<string>();
public void Add( string item ) => this.items.Add( item );
public string Describe() => string.Join( ", ", this.items );
}
public static class Program
{
public static void Main()
{
ShoppingCart cart = new ShoppingCart();
cart.Add( "Keyboard" );
cart.Add( "Mouse" );
Console.WriteLine( $"Cart: {cart.Describe()}" );
}
}
Cart: Keyboard, Mouse
See Also
Reference
ChildAttribute
ReferenceAttribute
ThreadUnsafeAttribute
Other Resources
Annotating an Object Model for Parent/Child Relationships (Aggregatable)
Working With Child Collections
Writing Thread-Safe Code with Threading Models