Open sandboxFocusImprove this doc

COM008: Child Collection Is Not an Advisable Collection

Severity Error
Reported by PostSharp.Patterns.Threading, PostSharp.Patterns.Model
Message The type of the child field or property "<Member>" is not supported. A child collection must be an AdvisableCollection<T>, an AdvisableDictionary<TKey, TValue> or an AdvisableHashSet<T>. The field or property can also have an interface type, as long as it is assigned to one of these collections at run time.

Cause

A threading model such as FreezableAttribute or ReaderWriterSynchronizedAttribute, and the [Recordable] aspect, propagate their behavior to the children of an object: the fields and properties marked with ChildAttribute. For a child collection, PostSharp adds this behavior to the collection object at run time, which only the advisable collections of the PostSharp.Patterns.Collections namespace allow. The standard collections, List<T>, Collection<T>, ObservableCollection<T>, Dictionary<TKey, TValue> and HashSet<T>, cannot be enhanced, so PostSharp reports COM008 when a child field or property has one of these types.

In the following example, the Addresses property of the freezable Customer class is a List<Address>.

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

namespace Errors.COM008_Error;

[Freezable]
public class Customer
{
    public string? Name { get; set; }

    // A child collection cannot be a List<T>.
    [Child]
    public List<Address> Addresses { get; set; } = new();
}

[Freezable]
public class Address
{
    [Parent]
    public Customer? Parent { get; private set; }

    public string? Line1 { get; set; }
}

public static class Program
{
    public static void Main()
    {
        var customer = new Customer { Name = "Joe Johnson" };
        customer.Addresses.Add( new Address { Line1 = "1 Main Street" } );

        ((IFreezable) customer).Freeze();

        Console.WriteLine( $"{customer.Name} has {customer.Addresses.Count} address." );
    }
}
error COM008: COM008_Error.cs(15,26): The type of the child field or property "Errors.COM008_Error.Customer.Addresses" is not supported. A child collection must be an AdvisableCollection<T>, an AdvisableDictionary<TKey, TValue> or an AdvisableHashSet<T>. The field or property can also have an interface type, as long as it is assigned to one of these collections at run time.

Resolution

  • Change the type of the field or property to the advisable collection that matches the standard one: AdvisableCollection<T> instead of List<T>, Collection<T> or ObservableCollection<T>, AdvisableDictionary<TKey, TValue> instead of Dictionary<TKey, TValue>, and AdvisableHashSet<T> instead of HashSet<T>.
  • Otherwise, give the field or property an interface type, such as IList<T>, and assign it an advisable collection.

In the following example, Addresses is an AdvisableCollection<Address>, so the collection is frozen with the customer.

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

namespace Errors.COM008_Fixed;

[Freezable]
public class Customer
{
    public string? Name { get; set; }

    // An AdvisableCollection<T> is frozen together with its parent.
    [Child]
    public AdvisableCollection<Address> Addresses { get; set; } = new();
}

[Freezable]
public class Address
{
    [Parent]
    public Customer? Parent { get; private set; }

    public string? Line1 { get; set; }
}

public static class Program
{
    public static void Main()
    {
        var customer = new Customer { Name = "Joe Johnson" };
        customer.Addresses.Add( new Address { Line1 = "1 Main Street" } );

        ((IFreezable) customer).Freeze();

        Console.WriteLine( $"{customer.Name} has {customer.Addresses.Count} address." );

        try
        {
            customer.Addresses.Add( new Address { Line1 = "2 Side Street" } );
        }
        catch ( ObjectReadOnlyException e )
        {
            Console.WriteLine( $"{e.GetType().Name}: {e.Message}" );
        }
    }
}
Joe Johnson has 1 address.
ObjectReadOnlyException: The object is frozen and cannot be modified.

See Also

Reference

ChildAttribute
AdvisableCollection<T>
AdvisableDictionary<TKey, TValue>
AdvisableHashSet<T>

Other Resources

Working With Child Collections
Compatibility of Threading Models