| 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>orObservableCollection<T>, AdvisableDictionary<TKey, TValue> instead ofDictionary<TKey, TValue>, and AdvisableHashSet<T> instead ofHashSet<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