在属性中传递静态数组

本文关键字:静态 数组 属性 | 更新日期: 2023-09-27 18:15:11

是否有可能绕过以下限制:

在类中创建静态只读数组:

public class A
{
    public static readonly int[] Months = new int[] { 1, 2, 3};
}

然后将其作为参数传递给属性:

public class FooAttribute : Attribute
{
    public int[] Nums { get; set; }
    FooAttribute()
    {
    }
}

——假设Box是a类的一个属性——

[Foo(Nums = A.Months)]
public string Box { get; set; }

我知道这不会编译,会导致这个错误:

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

是否有可能绕过这个以某种方式能够使用静态数组?我之所以这样问,是因为这样在维护方面会方便得多,因为我有很多属性。

在属性中传递静态数组

不幸的是这是不可能的。属性(包括其参数的值)由编译器放置到程序集元数据中,因此它必须能够在编译时对它们进行计算(因此对常量表达式的限制;对于数组创建表达式的异常很明显,因为否则你根本就不能有数组参数)。

相反,实际初始化A.Months的代码只在运行时执行。

基本上没有。

但是,您可以将子类化为属性并使用它,即
class AwesomeFooAttribute : FooAttribute {
    public AwesomeFooAttribute() : FooAttribute(A.Months) {}
}

或:

class AwesomeFooAttribute : FooAttribute {
    public AwesomeFooAttribute() {
        Nums = A.Months;
    }
}

,用[AwesomeFoo]代替。如果您使用反射来查找FooAttribute,它将按预期工作:

[AwesomeFoo]
static class Program
{
    static void Main()
    {
        var foo = (FooAttribute)Attribute.GetCustomAttribute(
            typeof(Program), typeof(FooAttribute));
        if (foo != null)
        {
            int[] nums = foo.Nums; // 1,2,3
        }
    }
}

你可以把它嵌套在A里面,这样你就可以用:

来装饰了。
[A.FooMonths]

或类似

简短回答:No.

但是你可以通过键来引用int数组:

public class A
{
    public static readonly Dictionary<int, int[]> NumsArrays 
              = new[]{{1, new[]{1,1,1}}, {2, new[]{2,2,2}}, {3, new[]{3,3,3}}};
    public const int Num1 = 1;
    public const int Num2 = 2;
    public const int Num3 = 3;
}
public class FooAttribute : Attribute
{
    public int NumsId { get; set; }
    FooAttribute()
    {
    }
}
[Foo(NumsID = A.Num3)]
public string Box { get; set; }
//Evaluation:
int id = (FooAttribute) Attribute.GetCustomAttribute(type, typeof (FooAttribute));
int[] result = A.NumsArrays[id];//result is {3,3,3}