Reputation: 692
I have the following attribute definition:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class TestAttribute : Attribute
{
public TestAttribute(List<string> values)
{
}
}
The following use of the attribute produces an error:
[Test(new List<string>() { "123", "456" }]
class A
{
}
The error is:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
Any help please? I'm using Visual Studio 2012 .NET 4.5.
I don't want to use params string[]
instead of List<string>
.
Upvotes: 1
Views: 762
Reputation: 388153
As the error message told you, you supply that as an argument to an attribute constructor. Generally anything you have to create with new
is not valid as that is not constant but allocated at run time.
As the error message suggests, you could just use an array instead. In your case, it’s very simple to do with a params array:
public TestAttribute(params string[] values)
{ }
Then you can use it like this:
[Test("123", "456")]
class A
{ }
Note though, that you have defined TestAttribute
to be only valid for methods, not for class declarations. So this will still fail.
I don't want to use
params string[]
instead ofList<string>
.
Well, you don’t have much of a choice, you could use a plain array, so you would have to write new string[] {"123", "456"}
instead—that doesn’t give you any benefit though.
If you really want a list, although there really shouldn’t be a need for it, you can create it in the constructor:
public TestAttribute(params string[] values)
{
List<string> valuesList = new List<string>(values);
}
I want to pass objects of specific types not something static.
You cannot ever pass anything dynamic to attributes. They are evaluated quite early when the declaration is processed, so at that time it’s unlikely that the rest of your code was executed.
Upvotes: 6
Reputation: 2709
Just like the message sais, it's simply not supported in c#. (The reason is that attributes are metadata and it should be possible to reflect/read metadata without executing code - such as initializing a list).
But you can use the params keyword:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class TestAttribute : Attribute
{
public TestAttribute(params string[] values)
{
}
}
[Test("123", "456")]
class A
{
}
Upvotes: 5