为什么合法?引用类型中的常量,从属性* on *类型开始,不带前缀类型名称?

时间:2014-01-14 16:56:15

标签: c# attributes constants

查看以下LINQPad计划:

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)
    {
    }
}

这样编译没有任何障碍。为什么呢?

具体做法是:

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

为什么我不写这个:

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

属性声明是否被认为是“内部”类型,因此在范围内?

2 个答案:

答案 0 :(得分:2)

属性实例声明的范围确实是它所附加的类型的范围,或者(在方法,参数等的情况下)包含它所附加的元素的类型。

我找不到任何具体的内容,尽管标准确实说:

  

可以在全局范围(指定包含程序集的属性)和类型声明(第16.6节),类成员声明(第17.1.4节),结构成员声明(第18.2节)中指定属性,interface-member-declarations(第20.2节),enum-member-declarations(第21.1节),accessor-declarations(第17.6.2节),event-accessor-declarations(第17.7节),形式参数列表的元素(§ 17.5.1)和类型参数列表的元素(第25.1.1节)。

虽然它没有明确说明类范围,但它确实将其与“全局范围”中更广泛的全局属性区分开来。

我注意到你班级的CIL是:

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
  }
}

CIL中的范围比C#更清晰

答案 1 :(得分:1)

当您将TestAttribute放在类上时,它会将其与该类关联,因此Name字段将在范围内。

您可以在此处阅读有关属性及其工作方式的所有内容:http://msdn.microsoft.com/en-us/library/aa664611(v=vs.71).aspx