| Severity | Warning |
| Reported by | PostSharp |
| Message | Cannot use <ReferencedKind> <ReferencedDeclaration> in <ReferencingKind> <ReferencingDeclaration> because the [Protected] constraint restricts it to the type that declares it and to the types derived from that type. |
Cause
The ProtectedAttribute constraint restricts a declaration that must be public or internal for technical reasons to the type that declares it and to the types derived from it, as the protected keyword would. PostSharp reports AR0108 on each method or type that uses the declaration from a type that does not derive from the top-level type that declares it: it calls the method or constructor, reads the field, or uses the type in a signature. Nested types of the declaring type have access.
<ReferencingDeclaration> is the declaration that holds the reference, and the message is reported at its location, not at the line of the reference.
AR0108 is a warning by default. Its severity comes from the Severity property of the constraint, which you can set to Error.
In the following example, ReportGenerator.FormatHeader is [Protected]. SalesReportGenerator derives from ReportGenerator and can call it, but Dashboard cannot.
using System;
using PostSharp.Constraints;
namespace Errors.AR0108_Error;
public class ReportGenerator
{
public string Generate( string title ) => this.FormatHeader( title ) + Environment.NewLine + "(no data)";
// A template engine needs this method to be public, but only report generators should call it.
[Protected]
public string FormatHeader( string title ) => $"=== {title.ToUpperInvariant()} ===";
}
public class SalesReportGenerator : ReportGenerator
{
public string GenerateSales() => this.FormatHeader( "Sales" ) + Environment.NewLine + "Total: 1250.00";
}
public class Dashboard
{
// This method calls ReportGenerator.FormatHeader, but Dashboard does not derive from ReportGenerator.
public string Render() => new ReportGenerator().FormatHeader( "Dashboard" );
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new SalesReportGenerator().GenerateSales() );
Console.WriteLine( new Dashboard().Render() );
}
}
warning AR0108: AR0108_Error.cs(23,19): Cannot use Method Errors.AR0108_Error.ReportGenerator.FormatHeader(System.String) in method Errors.AR0108_Error.Dashboard.Render because the [Protected] constraint restricts it to the type that declares it and to the types derived from that type.
Resolution
- Go through a member of the declaring type that is not restricted, instead of using the declaration directly.
- When the referencing type is a specialization of the declaring type, derive it from the declaring type.
- When the reference is an exception that you accept, suppress the warning on the referencing declaration with SuppressWarningAttribute. This does not work when the severity of the constraint is Error.
In the following example, Dashboard calls ReportGenerator.Generate, which calls FormatHeader inside ReportGenerator.
using System;
using PostSharp.Constraints;
namespace Errors.AR0108_Fixed;
public class ReportGenerator
{
public string Generate( string title ) => this.FormatHeader( title ) + Environment.NewLine + "(no data)";
// A template engine needs this method to be public, but only report generators should call it.
[Protected]
public string FormatHeader( string title ) => $"=== {title.ToUpperInvariant()} ===";
}
public class SalesReportGenerator : ReportGenerator
{
public string GenerateSales() => this.FormatHeader( "Sales" ) + Environment.NewLine + "Total: 1250.00";
}
public class Dashboard
{
// This method goes through ReportGenerator.Generate, which any class can call.
public string Render() => new ReportGenerator().Generate( "Dashboard" );
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new SalesReportGenerator().GenerateSales() );
Console.WriteLine( new Dashboard().Render() );
}
}
=== SALES ===
Total: 1250.00
=== DASHBOARD ===
(no data)
See Also
Reference
ProtectedAttribute
SuppressWarningAttribute
Other Resources