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. ericgu says:


    #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. TAG 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




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


      public class myclass


          bool value;

          bool Value




                  this.value = value;





  10. Maurits says:

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

  11. Maurits says:

    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:




    … 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. ericgu says:


    You’re correct – thanks.