Share via


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&quot; 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