I’m polishing up some code for a Windows Forms white paper on application layouts in Windows Forms 2.0. The paper will cover advanced uses of the ToolStrip control for creating navigational layouts, among other things. One of the samples is a VS Toolbox-style flyout panel. The code to implement this wasn’t too gnarly, except that in my first rev, I was new()ing up a whole lotta Point structs in slide-in and slide-out:
currentControl.Location = New Point(currentControl.Location.X + 20, currentControl.Location.Y)
Jim Galasyn, one of my colleagues on the team, asked why I was doing this. To put it simply, I did it this naively because the Location property of Control is lame. Location is of type Point, which is a struct. Structs are passed by value, not by reference, meaning that returning the Location property directly would pass a copy of the type on the stack. On top of that, for some reason, the source code for Control.Location in Windows Forms just goes ahead and new()s up a new Struct every time you access the Location property anyway! (That’s a good reason not to call this property extraneously, and to almost never call it in large loops.) So direct calls on Location are for naught.
I worked around this in my own application by caching a Point value, and operating on that using the Offset() method. This eliminated the constant creation of new Point structures on the stack, sped up my app, and make for somewhat cleaner code:
currentControl.Location = _CachedControlPoint
What’s frustrating is that, after 2-1/2 years writing Windows Forms documentation, I still get bitten by this. It’s so natural to call a property or a method and expect that to reflect on the associated object that exceptions such as these throw me for a loop. Sure, we can document this. We have documented it. But documentation can only do so much to defeat logic.
It would be nice, at the very least, to have an OffsetLocation() method defined on Control that eliminated the need for self-caching of Point objects. I know my product team has bigger fish to fry, but…come on, folks, pretty please? As a favor for l’il ol’ me? [insert eyelash-batting here]