The Importance of a Name
While I do use C# a fair bit, I’m not an early adopter of test releases of Visual Studio or new versions of the language. I try to keep up on what new features are coming, so when final releases are made I can dive right in, but I’ve fallen a bit behind on the syntax and implementation details for a few things in C# 3.0. My question now is: at what point did identifier names start trumping other indicators for semantic interpretation of code?
For a good long time now, statically typed language compilers have presented developers with a proposition that can loosely be stated thusly: you give your variables types so I know what to do with them, and then you can call them whatever you want so you know what to do with them. Now, it turns out that type annotations can be very useful for helping people understand code as well, but such information isn’t strictly necessary for productive development (e.g. dynamically typed languages and those with good type inferencing capabilities).
But now, it seems, the folks steering the C# ship are turning to identifiers to infer programmer intent in the form of object and collection initializers. The identifier-based mechanism for collection initializers is described here.
What I think is interesting about this is that such behavior is much more commonly found in dynamic languages, where there often isn’t as much developer-generated metadata available. C# let’s developers “mark up” their code with type specifications and attributes, so why aren’t we using those mechanisms instead of relying on compiler conventions and guess work? Automatic properties (also described in the first link above) can well be managed by using an attribute, which then avoids the somewhat odd issue of having a private field whose name nobody but the compiler knows. Collection initializers could benefit from having the appropriate
Add method decorated with an attribute, or implementing an interface that specifically defines the interface used by the collection initialization mechanism. Object initializers… well, that one I like except for the unifying of common property names (i.e. passing a property of one object to an object initializer without assigning it to a specific property, thus relying on the compiler to equate common names). It’s just strange to me that, what seem to me to be, more idiomatic C# techniques are not being used.
All that said, I am very interested to see how this all pans out. I use reflection constantly in my C# code. I very often build base classes, or frameworks, that are sensitive to field, property, and method declarations in sub-classes. These techniques can be used to eliminate masses of boiler plate code, and, ideally, minimize developer responsibility by relying on very compact behavior declarations, rather than imperative specification of how the behavior is to be accomplished. When I do this, I very often require that a default constructor be available (because constructors that take parameters can be a pain when instantiating objects programmatically), and I often do use identifier names as part of the patterns I’m looking for to trigger the metaprogramming routines. That style of development seems like just what C# 3.0 is heading towards. Rather than constructors with positional arguments, we throw a dictionary with some number of parameters at the constructor (beware developers who assume properties have been set in the constructor!). Rather than lean on potentially complicated inheritance, let’s look for idiomatic collection definition.
I’ve never had many reservations about doing this within the scope of a single project. All the developers can agree that declaring a
Connect method is going to trigger some framework-defined behavior. But does this kind of logic belong in the compiler for the underlying language? If the 80/20 rule applies to library design, does it also apply to compiler design?