C# 在属性中传递静态数组
是否有可能绕过以下限制: 在类中创建静态只读数组:C# 在属性中传递静态数组,c#,static,attributes,C#,Static,Attributes,是否有可能绕过以下限制: 在类中创建静态只读数组: 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类的一个
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类的一个属性---
我知道这将无法编译,并将导致此错误:
属性参数必须是常量表达式,typeof
属性参数的表达式或数组创建表达式
类型”
有没有可能绕过这个问题,使用静态数组?
我问,因为这将是更方便的维护明智的,因为我有很多财产
提前感谢。不幸的是,这是不可能的。编译器将属性(包括其参数的值)放入程序集元数据中,因此它必须能够在编译时对其求值(因此对常量表达式的限制;数组创建表达式显然是例外的,因为否则根本就不能有数组参数) 相反,实际初始化A.Months的代码只在运行时执行。基本上不是 但是,您可以对该属性进行子类化并使用它,即
class AwesomeFooAttribute : FooAttribute {
public AwesomeFooAttribute() : FooAttribute(A.Months) {}
}
或:
用[AwesomeFoo]
来装饰。如果使用反射查找footAttribute
,它将按预期工作:
[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]
或类似的简短回答:否
但您可以通过键引用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}
公共A类
{
公共静态只读字典NumsArrays
=新[]{1,新[]{1,1,1},{2,新[]{2,2,2},{3,新[]{3,3,3}};
公共常数int Num1=1;
公共const int Num2=2;
公共常数int Num3=3;
}
公共类footAttribute:属性
{
public int NumsId{get;set;}
footattribute()
{
}
}
[Foo(NumsID=A.Num3)]
公共字符串框{get;set;}
//评价:
intid=(FooAttribute)Attribute.GetCustomAttribute(type,typeof(FooAttribute));
int[]结果=A.NumsArrays[id]//结果是{3,3,3}
从概念上讲,“readonly”应该是“const”吗?可能是,但它们是:readonly关键字与const关键字不同。常量字段只能在声明字段时初始化。只读字段可以在声明或构造函数中初始化。因此,根据使用的构造函数,只读字段可以有不同的值。或者换句话说,属性需要在编译时确定,只读变量在运行时分配?这种理解正确吗?嗯。。。我想知道:如果你只在一个只有反射的环境中反射,会发生什么?@Jon是的,那你就完蛋了。元数据根本不知道内部发生了什么。如果您只能访问元数据,那么您所能说的就是“有一个awesomefootattribute
,我可以说它本身就是一个footattribute
”。然而,大多数人并不是只在反射环境中工作。事实上,我确实做了很多(通常是通过IKVM.Reflection)——我感觉到了你的痛苦:)有一分钟,我认为代码是等价的,编译器不厌其烦地看到字段是用一个新数组初始化的。。。这在理论上在这个特定的例子中是可能的,但作为一个特性,这当然是荒谬的,因为它在很多情况下都不起作用。谢谢你澄清这些。@Jon的确,这是99%的运行时间;但这是一个有用的技巧,因为大多数情况下都将使用运行时,而不是反射-only@MarcGravell:谢谢Marc,这是一个有趣的解决方案,尽管我负担不起在构造函数中添加新属性的费用:-(但在机会出现时请记住这一点!Thx,const有帮助
[A.FooMonths]
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}