Open sandboxFocusImprove this doc

AR0107: [Protected] Applied to a Declaration C# Already Restricts

Severity Error
Reported by PostSharp
Message Cannot use [Protected] on <Kind> <Declaration> because the <Kind> is already private or protected, or belongs to a private or protected type. [Protected] applies only to public or internal declarations.

Cause

The ProtectedAttribute constraint restricts a public or internal declaration to the type that declares it and to the types derived from it, as the protected keyword would, for a declaration that must be public or internal for technical reasons. When the declaration is private or protected, or belongs to a nested type that is private or protected, C# already gives this protection, and PostSharp reports AR0107 on the declaration.

PostSharp itself rejects the most direct cases before this check: applying [Protected] to a private or protected member reports PS0091. AR0107 remains for a member whose own visibility is public or internal but whose nested type is private or protected, as in the following example, where HeaderFormatter is protected.

using System;
using PostSharp.Constraints;

namespace Errors.AR0107_Error;

public class ReportGenerator
{
    protected class HeaderFormatter
    {
        // This method is public, but its class is protected, so C# already restricts it to derived classes.
        [Protected]
        public string Format( string title ) => $"=== {title.ToUpperInvariant()} ===";
    }

    public string Generate( string title ) => new HeaderFormatter().Format( title ) + Environment.NewLine + "(no data)";
}

public class SalesReportGenerator : ReportGenerator
{
    public string GenerateSales() => new HeaderFormatter().Format( "Sales" ) + Environment.NewLine + "Total: 1250.00";
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new SalesReportGenerator().GenerateSales() );
    }
}
error AR0107: AR0107_Error.cs(12,23): Cannot use [Protected] on method Errors.AR0107_Error.ReportGenerator+HeaderFormatter.Format because the method is already private or protected, or belongs to a private or protected type. [Protected] applies only to public or internal declarations.

Resolution

  • When the nested type does not need to be visible outside of its containing type and its derived types, remove [Protected]: the protected keyword already gives the protection.
  • When the nested type must be public or internal for technical reasons, change its visibility and keep [Protected] on the member.

In the following example, HeaderFormatter is public, and [Protected] restricts Format to ReportGenerator and its derived classes.

using System;
using PostSharp.Constraints;

namespace Errors.AR0107_Fixed;

public class ReportGenerator
{
    // The class is public, so [Protected] is what restricts the method to ReportGenerator and its derived classes.
    public class HeaderFormatter
    {
        [Protected]
        public string Format( string title ) => $"=== {title.ToUpperInvariant()} ===";
    }

    public string Generate( string title ) => new HeaderFormatter().Format( title ) + Environment.NewLine + "(no data)";
}

public class SalesReportGenerator : ReportGenerator
{
    public string GenerateSales() => new HeaderFormatter().Format( "Sales" ) + Environment.NewLine + "Total: 1250.00";
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new SalesReportGenerator().GenerateSales() );
    }
}
=== SALES ===
Total: 1250.00

See Also

Reference

ProtectedAttribute

Other Resources

Validating Architecture