Consider the following attribute.
internal class NiceAttribute : Attribute
{
private string _stuff;
public string Stuff
{
set { _stuff = value; }
}
}
When I try to use the attribute [Nice(Stuff = "test")] the compiler gives the following error.
‘Stuff’ is not a valid named attribute argument. Named attribute
arguments must be fields which are not readonly, static, or const, or
read-write properties which are public and not static.
What is the rational behind the requirement for the property to be readable?
Update
I will try to sketch my use case for having write-only properties on attributes.
interface ISettingsBuilder
{
Settings GetSettings();
}
class SettingsAttribute : Attribute, ISettingsBuilder
{
private readonly IDictionary<string, object> _settings =
new Dictionary<string, object>();
public Settings GetSettings()
{
// Use _settings to create an immutable instance of Settings
}
public string Stuff
{
set { _settings["Stuff"] = value; }
}
// More properties ...
}
There may be other implementations of ISettingsBuilder. For example one that offers a nice API to build settings through code.
I ended up with implementing my getters by throwing a NotImplementedException.
public string Stuff
{
get { throw new NotImplementedException(); }
set { _settings["Stuff"] = value; }
}
Can you think of a nicer way to do something like this?
I suspect the compiler is using a slightly misguided check to see whether you are accessing a private property hereEdit “we” have now located the actual source. For informational purposes, here is the full breakdown, but feel free to skip to the bottom.
(note how bug should be filed against the Mono compiler. I’ll think that one over for a while)
Compiler Error CS0617
It could seem that it is using some kind of lookup (akin to reflection) to make sure that the getter is accessible and if it isn’t, concludes that it must be private.
Which, of course, it doesn’t need to be 🙂
Mono Compatibility:
For fun, observe that the mono compiler has no problem whatsoever accepting this attribute: https://ideone.com/45fCX
Because of Reflection:
Of course it could be that the compiler requires attribute parameters to have reflectable values. If the property wasn’t publicly readable, you could only use reflection to ‘observe’ that the attribute is present, not with what parameter it was initialized.
I don’t know exactly, why such a design choicde would have been made, but it does make sense if you factor in reflection usage.Update @Arun posted the relevant quote that confirms this conjecture (thanks!):
So the reason must be: Attribute parameters must have reflectible values
Prize question: How does that work with positional parameters? How would one reflect those?