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 (16)

  1. 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?

  2. 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.

  3. Nick says:

    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.

  4. Garry Trinder says:

    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.

  5. Peter Ritchie says:

    TAG, good point.  e.g. this doesn’t work:

       public class myclass

       {

           bool value;

           bool Value

           {

               set

               {

                   @value = value;

               }  

           }

          }

  6. Denis says:

    One of the little things that VS 2005 did to make this nicer is color coding of keywords now takes into account its context. For example, value is colored as a keyword only in a setter.

  7. Yaakov says:

    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.

  8. Wesner Moise says:

    ""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.

  9. 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.

  10. The Perl equivalent would be "shift", which is comfortably familiar to anyone who’s written any batch files.

  11. And since you bring up Perl, I’ll note that Perl never has the problem of variable names colliding with anything… because in Perl, variable names always begin with a sigil that denotes the kind of variable it is:

    $scalar

    @array

    %hash

    … except for filehandles.

  12. 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…

  13. Dan McKinley says:

    How refreshing it is for this blog to actually have something to do with C# again.

  14. Miral says:

    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.

  15. Miral,

    You’re correct – thanks.

    Eric

Skip to main content