| Severity | Error |
| Reported by | PostSharp.Patterns.Caching |
| Message | Invalid [InvalidateCache] aspect on <Method>: there are several suitable overloads of the <MethodName> method. Set the AllowMultipleOverloads property to "true" to allow invalidation of all of them. |
Cause
The InvalidateCacheAttribute aspect identifies the methods to invalidate by name only. When the name designates several overloads, PostSharp keeps the cached overloads whose parameters can all be matched, by name and type, with the parameters of the invalidating method <Method>. An overload matches when the invalidating method has a parameter of the same name and of a compatible type for each of its parameters, except those marked with NotCacheKeyAttribute. An overload without parameters therefore matches any invalidating method.
When several overloads match, the aspect invalidates none of them by default, and PostSharp reports CAC009, so that you do not invalidate more cache items than you intend.
PostSharp reports the message on the declaration of the invalidating method.
In the following example, AddOrder has the customerId and year parameters, so it matches both overloads of CountOrders.
using System;
using System.Collections.Generic;
using System.Linq;
using PostSharp.Patterns.Caching;
using PostSharp.Patterns.Caching.Backends;
namespace Errors.CAC009_Error;
public record Order( int CustomerId, int Year, decimal Amount );
public class OrderService
{
private readonly List<Order> orders = new();
[Cache]
public int CountOrders( int customerId )
{
Console.WriteLine( $"Counting the orders of customer {customerId}." );
return this.orders.Count( o => o.CustomerId == customerId );
}
[Cache]
public int CountOrders( int customerId, int year )
{
Console.WriteLine( $"Counting the orders of customer {customerId} in {year}." );
return this.orders.Count( o => o.CustomerId == customerId && o.Year == year );
}
// The parameters of AddOrder match both overloads of CountOrders.
[InvalidateCache( nameof(CountOrders) )]
public void AddOrder( int customerId, int year, decimal amount )
{
this.orders.Add( new Order( customerId, year, amount ) );
}
}
public static class Program
{
public static void Main()
{
CachingServices.DefaultService.Backend = new MemoryCachingBackend();
var service = new OrderService();
Console.WriteLine( $"Orders: {service.CountOrders( 1 )}, in 2026: {service.CountOrders( 1, 2026 )}" );
service.AddOrder( 1, 2026, 100m );
Console.WriteLine( $"Orders: {service.CountOrders( 1 )}, in 2026: {service.CountOrders( 1, 2026 )}" );
}
}
error CAC009: CAC009_Error.cs(33,17): Invalid [InvalidateCache] aspect on Errors.CAC009_Error.OrderService.AddOrder(System.Int32, System.Int32, System.Decimal): there are several suitable overloads of the CountOrders method. Set the AllowMultipleOverloads property to "true" to allow invalidation of all of them.
Resolution
- When the invalidating method makes all the matching overloads stale, set the AllowMultipleOverloads property of the aspect to
true. Each call then removes the cache items of every matching overload. - Otherwise, give the overloads different names, so that the aspect can name only the one to invalidate.
In the following example, AddOrder invalidates both overloads of CountOrders, so both counts are computed again after the order is added.
using System;
using System.Collections.Generic;
using System.Linq;
using PostSharp.Patterns.Caching;
using PostSharp.Patterns.Caching.Backends;
namespace Errors.CAC009_Fixed;
public record Order( int CustomerId, int Year, decimal Amount );
public class OrderService
{
private readonly List<Order> orders = new();
[Cache]
public int CountOrders( int customerId )
{
Console.WriteLine( $"Counting the orders of customer {customerId}." );
return this.orders.Count( o => o.CustomerId == customerId );
}
[Cache]
public int CountOrders( int customerId, int year )
{
Console.WriteLine( $"Counting the orders of customer {customerId} in {year}." );
return this.orders.Count( o => o.CustomerId == customerId && o.Year == year );
}
// AddOrder invalidates both overloads of CountOrders.
[InvalidateCache( nameof(CountOrders), AllowMultipleOverloads = true )]
public void AddOrder( int customerId, int year, decimal amount )
{
this.orders.Add( new Order( customerId, year, amount ) );
}
}
public static class Program
{
public static void Main()
{
CachingServices.DefaultService.Backend = new MemoryCachingBackend();
var service = new OrderService();
Console.WriteLine( $"Orders: {service.CountOrders( 1 )}, in 2026: {service.CountOrders( 1, 2026 )}" );
service.AddOrder( 1, 2026, 100m );
Console.WriteLine( $"Orders: {service.CountOrders( 1 )}, in 2026: {service.CountOrders( 1, 2026 )}" );
}
}
Counting the orders of customer 1.
Counting the orders of customer 1 in 2026.
Orders: 0, in 2026: 0
Counting the orders of customer 1.
Counting the orders of customer 1 in 2026.
Orders: 1, in 2026: 1
See Also
Reference
InvalidateCacheAttribute
AllowMultipleOverloads
NotCacheKeyAttribute
Other Resources