Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this legal? Referring to a constant in a type, from an attribute *on* the type, without prefixing with type name?

Look at the following LINQPad program:

void Main() { }

[TestAttribute(Name)]
public class Test
{
    public const string Name = "Test";
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
[Serializable]
public class TestAttribute : Attribute
{
    public TestAttribute(string dummy)
    {
    }
}

This compiles without a hitch. Why?

Specifically:

[TestAttribute(Name)]
public class Test
{
    public const string Name = "Test";

Why don't I have to write this:

               vvvvv
[TestAttribute(Test.Name)]
public class Test
{
    public const string Name = "Test";

Is the attribute declaration deemed to be "inside" the type, and thus in scope?

like image 227
Lasse V. Karlsen Avatar asked Oct 20 '22 16:10

Lasse V. Karlsen


2 Answers

The scope of an attribute instance declaration is indeed that of the type on which it is attached, or (in the case of a method, parameter, etc.) the type containing the element on which it is attached.

I can't find anything specific on that, though the standard does say:

Attributes can be specified at global scope (to specify attributes on the containing assembly) and for type-declarations (§16.6), class-member-declarations (§17.1.4), struct-member-declarations (§18.2), interface-member-declarations (§20.2), enum-member-declarations (§21.1), accessor-declarations (§17.6.2), event-accessor-declarations (§17.7), elements of formal-parameter-lists (§17.5.1), and elements of type-parameter-lists (§25.1.1).

While it doesn't explicitly say anything about class scope, it does differentiate that from the wider scope of global attributes in "global scope".

I'd note that the CIL of your class would be:

class public auto ansi beforefieldinit SomeNamespace.Test extends [mscorlib]System.Object
{
  .custom instance void SomeNamespace.TestAttribute::.ctor(string) = (
    01 00 04 54 65 73 74 00 00
  )
  .field public static literal string Name = "Test"
  .method public hidebysig specialname rtspecialname instance void .ctor () cil managed
  {
    .maxstack 8
    ldarg.0
    call instance void [mscorlib]System.Object::.ctor()
    ret
  }
}

The scoping in CIL is much clearer than in C#

like image 69
Jon Hanna Avatar answered Oct 24 '22 00:10

Jon Hanna


When you put the TestAttribute on the class it associates it with that class so the Name field would be in scope.

You can read all about Attributes and how they work here: http://msdn.microsoft.com/en-us/library/aa664611(v=vs.71).aspx

like image 36
jzworkman Avatar answered Oct 23 '22 23:10

jzworkman