问题 应用C#属性时允许什么语法?


这些是迄今为止我见过的最常见且唯一的模式:

[AttributeFoo]
[AttributeBar("Hello world!")]
[AttributeBaz(foo=42,bar="Hello world!")]
public class Example {}

属性语法 好像 你正在调用一个构造函数。在C#支持可选和命名参数之前,属性的命名参数是唯一可见的差异。

C#编译器是否允许其他任何内容?喜欢 params 参数或对象/集合初始值设定项?

也可以看看: 应用属性 在MSDN上


7164
2018-01-18 21:56


起源

我曾经说过 string[] 属性中的初始值设定项。 - JohnL


答案:


AFAIK,命名参数只允许整数类型。不幸的是,我没有提到支持这一点,我只是通过自己的实验来学习它。

在尝试使用对象初始化器时,我从编译器中收到此错误:

属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式

虽然这个 文件 有几年了,它有我想要的参考信息:

属性参数限制为的常量值   以下类型:

  • 简单类型(bool,byte,char,short,int,long,float和double)
  • 系统类型
  • 枚举
  • object(对象类型的属性参数的参数必须是上述类型之一的常量值。)一维   任何上述类型的阵列

这样可行:

//Test attribute class
[AttributeUsage(AttributeTargets.All)]
internal class TestAttribute : Attribute
{
    public int[] Something { get; set; }
}

//Using an array initialiser - an array of integers
[TestAttribute(Something = new int[]{1, 2, 3, 4, 5})]
public abstract class Something

虽然这不会:

//Test person class
internal class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        this.Name = name;
    }
}

//Test attribute class
[AttributeUsage(AttributeTargets.All)]
internal class TestAttribute : Attribute
{
    public IEnumerable<Person> Something { get; set; }
}

//This won't work as Person is not an integral type
[TestAttribute(Something = new Person[]{new Person("James")})]

编辑:只是详细说明,属性构成了应用它们的构造的元数据的一部分(在生成的IL中),因此必须在编译时确定属性类的成员;因此将属性参数限制为常量值。


4
2018-01-18 22:02





除了别人所说的,我还想指出属性也可以用逗号分隔。

[AttributeFoo, AttributeBar("Hello world!"), AttributeBaz(foo=42,bar="Hello world!")]
public class Example {}

5
2018-01-18 23:14



这是一种不好的做法;它的可读性较差。 - Jowen


位置参数是必需的,必须在任何命名参数之前;它们对应于属性构造函数之一的参数。命名参数是可选的,对应于属性的读/写属性。在C ++,C#和J#中,为每个可选参数指定name = value,其中name是属性的名称。在Visual Basic中,指定name:= value。

从您提供的链接。看起来这是唯一允许的事情。基本上,正如您所提到的,您正在将构造函数与嵌入式属性初始化逻辑相结合。


1
2018-01-18 21:59



虽然我认为这对于回答这个问题还有很长的路要走,但却缺少对论证本身允许哪些类型的表达式的讨论。例如,常量,数组创建表达式, typeof() 表达等 - binki