Irony, thy name is C#

Intro:

So i was having a conversation with the team about a small change I'd like to make to C#. Right now, C# has the concept of "contextual keywords". I.e. identifiers that can have special meaning when used in special locations, but which are otherwise completely legal identifiers for the user in all other conditions. Good examples of this are 'partial', 'yield', and 'where'. In C# 2.0 "yield" is now used in iterator contexts to indicate that you are yielding a value, or terminating iteration. However, in C# 1.0 "yield" was a perfectly valid identifier. In fact, I used it all the time because i had a type called "class Yield" which indicated the 'yield' of a gramamtical production in a language. So how could we add this "contextual keyword" without breaking code that had been previously written? Simple, we added it in a way such that if you tried to use it with its new meaning you would be writing code that couldn't exist in previous versions of the language. Specifically, to use "yield" you must use it like so:

yield return 4;

yield break;

By forcing you do use "yield" before a "return" or "break" keyword we ensure that we won't be conflicting with any code that you've written in the past (where this would have been illegal).

So this is great. We can add more functionality to the C# language without impacting you negatively.

Now, i was doing some C# coding and i was trying to use a common java idiom that i find very natural. Specifically:

InputStream in = ...;

OutputStream out = ...;

But, lo and behold, i'm not allowed to! Turns out 'in' and 'out' are reserved keywords and i can't use them as variable names. So i was giving it a little thought and i realized: "hey these don't have to be keywords, we could make them contextual keywords!". Why is that the case? Well, let's look at how 'out' is used. 'out' can only be used in three places, the declaration of a method or delegate and the call site of to a method, a-la:

void Foo(out int i) { //method declaration

      int num;

      Foo(out num); //method call

However, as a user, you are not allowed to write code with arbitrary identifiers preciding an argument to a method, or preceding the type in a method declaration. So we could make 'out' contextual, without screwing up any of your code, and while now allowing it as an identifier name. What would be interesting is that we would now allow this type of code:

void Foo(out out out) { //method declaration

 

But no one will do that (or else they'll be beaten in the code review). Regardless, such cases exist today with things like "where". You could say:

void Foo<where>() where where : where

 

and we won't stop you. Just in practice this will never happen. (and, if it did, the IDE colorization would help you out a lot).

A similar story holds for "in", which is reserved solely for the "foreach" construct. I won't delve deeper into this since i think you get the idea.

 

Story:

So we're having a conversation about things we'd like to see in the next version of the language. I bring this up, mention the benefits and how it would just be a nice thing to do with very low cost. There is agreement, but a lot of wondering "is the benefit so small that we shouldn't even be looking at this". Ok, so we talk about it for like 2 minutes and then move on. At some point we get to another suggestion of mine whereby i think that we should allow a delegate to bind to a property. i.e. you could have the following:

delegate int ProducesInt();

delegate void TakesInt(int i);

class Person {

      int Age { get { ... } set { ... } }

      void Foo() {

            ProducesInt pi = new ProducesInt(this.Age);

            TakesInt ti = new TakesInt(this.Age);

Of course, this isn't allowed today because the argument to a delegate must be a method. But this always ends up getting in my way and i have to create nasty workarounds. Since we're the compiler we know what the delegate binds to, and we know about the synthesized methods created for the getter and setter, and so it would be pretty trivial to pass the right method object to the delegate's constructor. In the cases above we would just traslate that to:

           

ProducesIntpi =newProducesInt(this.get_Age);

TakesIntti =newTakesInt(this.set_Age);

So, we got to talking about it a bit more, and we came back to the old discussion where we get a lot of requests from customers for an easy way to refer to a property's getter or setter easily in the language. Me, thinking i was so brilliant, said: "how about the following idea:

           

ProducesIntpi=newProducesInt(this.Age.get);

TakesIntti =newTakesInt(this.Age.set);

By using the 'get' or 'set' keyword after referring to a property, we will then get the appropriate method off of it that you can now use. Handy for this situation and others as well!"

And, instantly, someone responded: "because 'get' and 'set' are contextual keywords, and it's perfectly valid for them to be members of a type. You now have an ambiguous situation where you might be referring to the getter of the property, or a field on the object that is returned."

Bam. Right after I'd argued passionately about moving more keywords to be contextual.

I hadn't considered that reserving keywords could actually be useful because they did allow us a lot more flexibility with creating new language features. If we'd reserved 'get' and 'set', then this would be trivially easy to solve, but now we're stuck in a place where doing that is no longer as elegant or easy, and we don't want to bog down the language with more uglyness.

So i backed out of my request for 'in' and 'out' to become contextual. After all, it's not really hurting people that badly, and it does give us more flexibility in the future if we find that those keywords would be perfect for something else. It also meant that i could focus more on getting features that i really want into the language (like covariant return types. have you voted yet???).