When is a keyword not a keyword?
Many languages have a very strict definition of what a keyword is. The word "for" has a specific meaning, and you can't use it anywhere else in the program.
C# does have this kind of keyword - you can find the usual list of keywords in the docs - but it also has what is known as a contextual keyword, where a word functions like a keyword, but only in specific situations.
Contextual keywords are a way to expand the number of keywords you can use without infringing into the identifier space of the user.
One of the best examples is the set accessor of a property, which typically looks something like this:
string Name
{
set { name = value; }
}
In the set accessor, you need to have a way to indicate the value the user assigned to the property. This could (perhaps - I haven't thought about it deeply) have been done with some weird concatenation of symbols, such as "<|", but C# isn't Perl, so it made more sense to use a word, and "value" is easy to understand.
But people use "value" as a variable name ALL THE TIME, and they're not going to be happy if you steal it, especially for a small feature.
So, instead of making "value" a true keyword, you make it a contextual keyword. In this case, "value" is reserved only within a set accessor, but you can freely use it elsewhere.
Comments
- Anonymous
March 08, 2006
I actually encountered a quirk in the "value" pseudo-keyword last week.
I had code which was almost working but a particular property kept being lost. My code looked like this:
private string value;
public string Value {get {return value;} set {@value = value;}}
I thought that using "@value" to escape the keyword would be enough to get it treated as an identifier, but apparently it isn't. Also, apparently it is legal to assign to the magic "value" pseudo-variable. So this code was perfectly legal and compiled with no errors or warnings, but the set accessor was a no-op!
Obviously the correct fix was to make the setter say "this.value = value;". But I was wondering if you could shed any light on the decisions (1) to make the "@" modifier not have its usual semantics of overriding the "keywordness" here, and (2) to make "value" writable? - Anonymous
March 08, 2006
Stuart,
#1 is probably a bug, though I haven't though deeply about it and there may be a valid reason for it.
I can see a small amount of utility making "value" writable, but not really enough to permit it. I don't think the spec covers this case - if it doesn't, it's undefined behavior. - Anonymous
March 08, 2006
The value example is a great one to bring up, because I could never understand why a new keyword was needed to make this feature work in the first place. As much as I abhore VB.NET, their idea of allowing you to name the variable would have been much better I think... something along the lines of...
public string MyProperty
{
get { return _property; }
set ( string newValue ) { _property = newValue; }
}
Of course thats all water under the bridge now. - Anonymous
March 08, 2006
Hi Stuart and Eric,
@value is same as value. Value is not keyword - but "The implicit parameter of a set accessor is always named value." (Ecma 334 sec. 17.6.2 Accessors)
To confirm this - check see also "The following identifiers have special meaning in the syntactic grammar, but they are not keywords:
... value ...
For convenience and clarity, theseidentifiers appear as terminals in the syntactic grammar; however, they are identifiers." (sec 9.4.3 Keywords)
Usage of @ allow to create identifier from keyword. But since "value" is already identifier - @ has no effect. Usage of this.value is the only correct thing.
IMHO, This is well-defined in specification dispute result in somethat unexpected results. - Anonymous
March 08, 2006
TAG, good point. e.g. this doesn't work:
public class myclass
{
bool value;
bool Value
{
set
{
@value = value;
}
}
} - Anonymous
March 08, 2006
The comment has been removed - Anonymous
March 08, 2006
As long as VS paints the "value" identifier as a keyword anywhere in the code, it's completely unusable in other contexts excepth than in property setters.
C# was designed for simplicity, and painted words in the middle of your code is confusing and time wasting. - Anonymous
March 08, 2006
""value" is reserved only within a set accessor"
Technicality: value is used in all accessors that take a value (add, remove, set), but otherwise you are right. - Anonymous
March 08, 2006
How about just using "this.value" instead of having any ambiguity?
I always use "this." to prefix members. Helps single them out of all the variables.
So:
public class myclass
{
bool value;
bool Value
{
set
{
this.value = value;
}
}
}
Works. - Anonymous
March 08, 2006
The Perl equivalent would be "shift", which is comfortably familiar to anyone who's written any batch files. - Anonymous
March 08, 2006
The comment has been removed - Anonymous
March 08, 2006
At least you get a compile-time error with C#. JavaScript has a lot of these implicit things, like the parameters list of function parameters. Not only will JavaScript give you no warning at runtime or compile time (there's none), but JS being a dynamic language, it will actually silently let you overwrite the parameters array, with results varying across browsers... - Anonymous
March 08, 2006
How refreshing it is for this blog to actually have something to do with C# again. - Anonymous
March 08, 2006
Actually value isn't a keyword at all, it's just an implicit parameter (the same as "this" in regular C++, though I think .NET treats it differently).
The setter, when compiled to IL, becomes a method with a signature approximately like:
public void set_Value(string value)
... and like all (non-ref/out) parameters in C#, you can reassign the variable without affecting whatever was originally passed in to the method. - Anonymous
March 08, 2006
Miral,
You're correct - thanks.
Eric - Anonymous
May 26, 2009
PingBack from http://backyardshed.info/story.php?title=eric-gunnerson-s-c-compendium-when-is-a-keyword-not-a-keyword