简体   繁体   中英

C# attribute naming

Does the C# compiler identify inherited Attribute classes to check if they contain the word 'Attribute'? In the below example, [Blah], [BlahA], and [BlahAttribute] are available attributes

    [AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
    public class BlahA: Attribute
    {
        //stuff
    }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
    public class BlahAttribute: Attribute
    {
        //stuff
    }

    //acceptable
    [BlahA]
    [Blah]
    [BlahAttribute]

The specification is rather clear on this:

A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an attribute class. The declaration of an attribute class defines a new kind of attribute that can be placed on a declaration. By convention, attribute classes are named with a suffix of Attribute. Uses of an attribute may either include or omit this suffix.

Further down under Attribute specification:

By convention, attribute classes are named with a suffix of Attribute . An attribute_name of the form type_name may either include or omit this suffix. If an attribute class is found both with and without this suffix, an ambiguity is present, and a compile-time error results. If the attribute_name is spelled such that its right-most identifier is a verbatim identifier (...), then only an attribute without a suffix is matched, thus enabling such an ambiguity to be resolved.

( source )

Since the spec allows users to either include or omit this suffix, the C# compiler also allows both. In your case, [BlahA] refers to BlahA , while [Blah] and [BlahAttribute] refer to BlahAttribute . If you defined an attribute with the name Blah , [Blah] would be ambiguous and you'd have to resolve it either by specifying [BlahAttribute] or using the verbatim identifier [@Blah] .

UPDATE:

I was lurking through Roslyn's source and completely by accident I stumbled upon the bits responsible for this part of the spec. You can find them in Microsoft.CodeAnalysis.CSharp.Binder.Binder_Lookup (at least as of 2020-05-19). It so happens that a rather interesting edge-case is described there. When resolving the attribute's type they look for Foo and FooAttribute as mentioned above. If only one of them is viable they choose that one, if both are then an ambiguity is reported. BUT if one of them is viable and the other is ambiguous itself, they generously choose the single viable option. To illustrate this, consider:

namespace A
{
    class FooAttribute : System.Attribute
    {

    }
}

namespace B
{
    class FooAttribute : System.Attribute
    {
    }
}

namespace C
{
    class Foo : System.Attribute
    {
    }
}

namespace D
{
    using A;
    using B;
    using C;

    [Foo] // Attribute resolution.
    class Bar 
    {
    }
}

The candidates for attribute resolution are A.FooAttribute and B.FooAttribute when looking with the Attribute suffix, as well as C.Foo when looking without it. The first choice is ambiguous - the compiler wouldn't be able to decide between A 's and B 's version - so C.Foo is chosen and the above code compiles. Now remove either of the using A or using B directives. Suddenly, only one FooAttribute is a viable candidate and there is an ambiguity between it and C.Foo . Try it !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM