McFunley: did you name this page something impossible to remember correctly on purpose? McFunley: this is a good anti-querystring hacking technique DarrelHerbst: the twocheckboxcolumn.aspx? DarrelHerbst: i remember it DarrelHerbst: your mind is addled with coffee McFunley: i typed "twocolumncheckbox" and "twocheckcolumnbox" and "boxcolumnchecktwo" before I got it right DarrelHerbst: addled
Archive for January, 2005
Jan
17
2005
Thinking Better Tech Designs
Where I work, there are programmers of widely varying skill levels all working on a single project. Some pieces tend to get behind, and some finish much more quickly. There are a seemingly endless number of integration problems. I am daily pondering what the differences are in the way people develop, and how I can communicate good ideas in a way that will help people reach that “eureka” moment where they get it.
Generally speaking, I’ve been pretty bad at it. I’ve tried explaining inheritance with stories, shaking people by their collars, etc, nothing really seems to work. The result is that people write code the way they always have: messy, hard to understand, hard to transfer to another owner, hard to change without creating new bugs.
Today this SLAR on System::Console got me thinking. Particularly, this line:
This class is a classic example of “design in reverse.” Before we designed this class we knew what we wanted the Hello World example to look like:
Console.WriteLine ("Hello World");
Well, there it is. That might be my own “eureka moment.” Write an API for yourself as you go. For every task you have to accomplish, ask yourself this:
If I had access to an oracle that could do my task for me, how would I want to use it?
Then start building that oracle. It’ll have steps that seem hard too, but use more oracles and more black boxes.
Another important point is to avoid thinking about code as much as you can.
Now, there are (obviously) a lot of steps between being a programming neophyte and being in the top few percent of software engineers. Most people need to get a lot of bad code out of their system before they’re much good. And this is certainly an oversimplification of thinking like a good developer.
Thinking of the best questions to ask your oracles can be a subjective, soft science too–but hopefully this is a decent starting point.
Jan
15
2005
Thread Safety in VB-2003 Events
Brad Abrams had a recent post about how the usual way of raising an event in C#:
protected virtual void OnMyEvent(EventArgs e)
{
if(MyEvent != null)
{
MyEvent(this, e);
}
}
is not threadsafe. Purely out of curiosity, I wondered if VB handles this the correct way:
protected virtual void OnMyEvent(EventArgs e)
{
EventHandler handler = MyEvent;
if(handler != null)
{
handler(this, e);
}
}
Since VB abstracts this away with the RaiseEvent keyword. Unfortunately it doesn’t seem to, as this code:
Protected Overridable Sub OnMyEvent(ByVal e As EventArgs)
RaiseEvent MyEvent(Me, e)
End Sub
Compiles to this:
.method family newslot virtual instance void OnMyEvent([mscorlib]System.EventArgs e) cil managed
{
// Code Size: 22 byte(s)
.maxstack 8
L_0000: ldarg.0
L_0001: ldfld [mscorlib]System.EventHandler VbConsoleApp.Test::MyEventEvent
L_0006: brfalse.s L_0015
L_0008: ldarg.0
L_0009: ldfld [mscorlib]System.EventHandler VbConsoleApp.Test::MyEventEvent
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, [mscorlib]System.EventArgs)
L_0015: ret
}
Which has a race condition–it should store the delegate in a local. Generally, my answer to all of these questions is “it is fixed in 2005” – so I’m going to just assume that that is the case here.
Jan
13
2005
HttpModule for Performing a Custom Action for Certain Urls
I wrote this collection of classes over the holidays as part of a side project and forgot about it. Today at work I needed basically exactly the same thing, but unfortunately I didn’t have it handy and had to recreate it from scratch.
This is a way to execute any action you please for requests against url’s matching one or more regular expressions. Today at work, I used it to install a response filter for a specific set of .aspx pages. I can think of at least a few more reasons someone might want something like this, so I’m posting it.
using System;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Collections;
using System.Web;
namespace McKinley.Web
{
/// <summary>
/// An abstract <see cref="T:System.Web.IHttpModule"/> that checks
/// the url of each incoming request against one or more regular
/// expressions. When a match is found, a custom action is
/// performed.
/// </summary>
public abstract class BaseRegexModule : IHttpModule
{
private RegexChain _chain;
/// <summary>
/// Reads the list of regular expressions to match from
/// the configuration settings. Hooks the beginning of
/// each request to perform the checks.
/// </summary>
public void Init(HttpApplication context)
{
Hashtable settings = (Hashtable)ConfigurationSettings.GetConfig(this.ConfigSectionName);
if(settings != null)
{
_chain = new RegexChain();
foreach(object val in settings.Keys)
{
string pattern = val as string;
if(pattern != null && pattern.Length > 0)
{
_chain.Add(pattern);
}
else
{
throw new ConfigurationException(
"The regular expression pattern may not be empty.");
}
}
}
context.BeginRequest += new EventHandler(BeginRequest);
}
/// <summary>
/// Tries to match the raw url against the list of expressions
/// given to the module. If a match is found, calls the abstract
/// <see cref="M:CustomAction"/> method.
/// </summary>
private void BeginRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if(application != null)
{
HttpRequest request = application.Request;
if(request != null && _chain.IsMatch(request.RawUrl))
{
CustomAction(application);
}
}
}
/// <summary>
/// This must be overridden to provide the name of the configuration
/// section for the concrete module class. The section is presumed
/// to use a <see cref="T:System.Configuration.DictionarySectionHandler"/>.
/// </summary>
protected abstract string ConfigSectionName { get; }
/// <summary>
/// This must be overridden to define a custom action to be performed
/// when one of the regular expressions are matched against the
/// request's URL.
/// </summary>
protected abstract void CustomAction(HttpApplication context);
public void Dispose() { }
public BaseRegexModule() { }
}
/// <summary>
/// This is an efficient utility class for a list of
/// regular expressions evaluated together.
/// </summary>
internal class RegexChain
{
private class Node
{
public Regex Expression;
public Node Next;
public Node(Regex r)
{
Expression = r;
}
}
private Node _head;
private Node _tail;
/// <summary>
/// Returns true if the given string is a match
/// for any of the regular expressions in the chain.
/// </summary>
public bool IsMatch(string input)
{
Node n = _head;
while(n != null)
{
if(n.Expression.IsMatch(input))
{
return true;
}
n = n.Next;
}
return false;
}
/// <summary>
/// Adds the given pattern to the chain of regular
/// expressions.
/// </summary>
public void Add(string pattern)
{
Node n = new Node(new Regex(pattern));
if(_head == null)
{
_head = n;
}
else
{
_tail.Next = n;
}
_tail = n;
}
}
/// <summary>
/// This is a <see cref="T:System.Configuration.IConfigurationSectionHandler"/>
/// that can be used with a class derived from
/// <see cref="T:McKinley.Web.BaseRegexModule"/>.
/// </summary>
public class RegexModuleSectionHandler : DictionarySectionHandler
{
protected override string KeyAttributeName
{
get { return "pattern"; }
}
}
}
And there you have it. Here’s an extremely simple example class that uses this to set a cookie for matching url’s.
public class ExampleRegexModule : BaseRegexModule
{
public ExampleRegexModule() { }
protected override void CustomAction(System.Web.HttpApplication context)
{
context.Response.AppendCookie(new HttpCookie("Oscar", "Is god"));
}
protected override string ConfigSectionName
{
get { return "mckinley.web/exampleRegexModule"; }
}
}
And finally, here are the web.config entries you’d need to install this HttpModule.
<configSections>
<sectionGroup name="mckinley.web">
<section
name="exampleRegexModule"
type="McKinley.Web.RegexModuleSectionHandler, McKinley.Web"
/>
</sectionGroup>
</configSections>
<mckinley.web>
<exampleRegexModule>
<add pattern="somepage.aspx" />
</exampleRegexModule>
</mckinley.web>
<system.web>
<httpModules>
<add name="example"
type="McKinley.Web.ExampleRegexModule, McKinley.Web" />
</httpModules>
<system.web>
Jan
12
2005
Significant Digits for the Innumerate
Suppose you ask me, “how wide is that picture frame?” (No, nevermind why you care how wide the picture frame is. This is a little device I call, “using narrative to make a semi-technical thing sound approachable.)
“About nine inches,” I would say.
Now, suppose your friend Friedrich asks you how wide the picture frame is, and I’m not in the room (let’s say I’m asleep—that’s where I’m a pirate!). You happen to know that Friedrich is of the German persuasion, and if you give him a number in English units he’ll scoff at you and possibly destroy your apartment with a Stuka divebomber.
Thinking quickly, you refer to your wristwatch calculator which you have been wearing since 1988 (in this narrative, your sense of style is atrocious). “There are 2.54 centimeters in an inch – I remember that from high school,” you think to yourself. Doing the multiplication, you smugly report to Friedrich that the picture frame is 22.86 centimeters wide.
Everybody’s happy, right? Not so fast, Copernicus.
I only told you the frame was “about nine inches” wide, remember? That could possibly mean 8.556 inches, 9.210 inches—you really can’t be sure. As a measuring device, I am lazy and inept. Do you want to be held responsible for my lax attitude? No, of course you don’t.
You are really only justified in telling Freddy-boy that the frame is about 20 centimeters wide. Giving him the extra digits of that number just give it the illusion of precision where none exists.
Friedrich measures the frame himself and gets less than 22 centimeters. He punches you in the stomach and leaves you wincing in pain on the floor, cursing me for not giving you a better figure in the first place. Sorry, I just couldn’t be bothered. (You made your bed, now lie in it, dammit!!!)
Oh yes, my point. Well, this kind of thing applies to a lot more than the picture on my desk. If I tell you that you can get $1.32 for a Euro, and $1.89 for a British Pound, you might similarly do the math and tell me that therefore, you can get 0.6984126984126984126984126984127 British Pounds per Euro. Well, you’d be nuts.
Jan
10
2005
Downloading a file async
I suppose that’s one way you might do it, but here is another:
private void button1_Click(object sender, System.EventArgs e)
{
WebRequest request = WebRequest.Create("http://www.mcfunley.com/stuff/hi.txt");
AsyncCallback callback = new AsyncCallback(this.GotFile);
IAsyncResult res = request.BeginGetResponse(callback, request);
}
private void GotFile(IAsyncResult r)
{
if(this.InvokeRequired)
{
this.Invoke(new AsyncCallback(this.GotFile), new object[]{r});
return;
}
WebRequest request = (WebRequest)r.AsyncState;
WebResponse response = request.EndGetResponse(r);
using(StreamReader reader = new StreamReader(response.GetResponseStream(), true))
{
this.richTextBox1.Text = reader.ReadToEnd();
}
}
Jan
09
2005
Re: “Best Method Names Ever”
From Brad Abrams.
I would have to say the best function name ever is definitely Function Batman.
But if we’re limiting it to Microsoft products, I guess I’d have to say I’m often surprised by the number of internal framework methods that are labeled “hacks.”

Jan
09
2005
.NET Math Quiz
I’ve been having a lot of fun with this post on .NET Undocumented.
If
x,y,zare ints, …1. If
x < 0, then-x > 0.False,
unchecked(-int.MinValue) == int.MinValue.2. If
x = -x, thenx = 0.False (see 1)
3. If
x - y > 0, thenx > y.False,
unchecked(int.MinValue - int.MaxValue) == 14. If
xandyare positive, thenx + y > x.False,
unchecked(int.MaxValue + 1) < int.MaxValue5. If
xandyare positive, then(double)x * (double)y = (long)x * (long)y.True – I don’t think this can’t be broken over the range of the integers. Not so over the longs, though.
6. If
x - y > 0andy - z > 0, thenx - z > 0.False, use
int x = int.MaxValue-1;
int y = -1;
int z = int.MinValue;This gives you
x - y == int.MaxValue,y - z == int.MaxValue, andx - z == -1.
If
x,y,zare doubles, …1.
x = x.False.
double.NaN != double.NaN.2. If
x > yisfalse, thenx < = yistrue.False – use
double.NaNfor both.3. If
x > 0, thenx - x = 0.False.
double.PositiveInfinity - double.PositiveInfinity == double.NaN4. If
xandyare positive integers, thenx + y > x.This is true because at the boundary condition,
double.MaxValue + double.MaxValue == double.PositiveInfinity.Note that this is different from the behavior of longs or ints. It is only true for integer doubles, though, because
x + double.Epsilon == x.5. If
xandyare integers andx > 0, then the statement “x + y = x for all y” is false for allx.True.
6. If
x <= 0isfalse, thenx > 0.Both statements are false for
double.NaN.7. If
xandyare longs, then(double)(x + y) = (long)(x + y).This is true because of the order of operations, but it does not hold for
(double)x + (double)y.8. if
x.Equals(y), thenx = y.This is false for
double.NaN.9. If
x.Equals(-x), thenx = 0.This is false for
double.NaN.10. if
x.ComparesTo(y) < 0, thenx < y.This is false where x is
double.NaN.
Note: You don’t need to use the unchecked keyword for the counterexamples using it to be valid; it is easy enough to come up with examples that will pass as long as runtime checks are off. I just used it so that my answers would be brief and would compile.
Jan
08
2005
Moore’s Law and the Free Lunch
This article was brought to my attention from a few sources. The general theme here is, “concurrency is going to be really important as processors begin to hit physical limits, and these kinds of programs are harder to write.” I thought I would give my spin on it. Here is another one-sentence summary of that article, childishly represented using Windows Paint.

At the admitted risk of sounding too much like a doomsday prophet, my prediction can be summed up as follows: despite attempts at tool and language support (for instance, CΩ), this is going to be painful for a large percentage of developers. Software cycles will probably take a big turn for the worse, so you might be better off working on the quantum computers in your garages now.
My reasoning is heavily influenced by the alleged “object revolution.” The fact is, you can’t claim to be doing object-oriented development just by virtue of using a language that has object-oriented features. And you can’t reap the benefits of doing object-oriented development in that case, either. In this day and age, I still see a ton (scores… hundreds.. maybe thousands) of methods that are 200 lines long and take twelve arguments. Now you can put a “virtual” in front of a method like that, but there’s obviously still a problem.
I like this quote from Object Thinking:
Both software engineering and object orientation have achieved a strange status - everyone claims to be doing them without really doing so.
The thesis of that book is that OOP and traditional programming take drastically different mindsets. Changes in mindsets can be really difficult to accomplish. Tools help you but they don’t automatically make you good at the task at hand. We’ve got great OOP tools now, but I think a lot of people still work on teams where deadlines are missed, integrating code written by different people is hard, and any number of shortcuts leads to a mess of spaghetti. We get away with it to an extent, mostly because it is accepted that software projects are late and contain bugs. We work way too hard in the process, though.
And as accurate as I think that is for the “object revolution”, it is only more accurate for the upcoming “concurrency revolution.” Writing a multithreaded app is a lot different than writing a single threaded app.
It could be good news for the highly motivated / educated, but as in any field that is the minority. I’m looking forward to the challenge, but purely for selfish reasons.
Jan
05
2005
The VB Compiler and Late Binding
Something interesting I came across today. Two seemingly identical loops in two different languages:
for(int i = 0; i <= 10000000; i++)
{
TimeSpan t2 = DateTime.Now.Subtract(t);
// assume we do something more interesting in
// a real program...
}
Dim t As DateTime = DateTime.Now()
For i As Integer = 0 To 10000000
Dim t2 As TimeSpan = Now.Subtract(t)
' assume we do something more interesting in a
' real program...
t2 = Nothing
Next
There is a difference, obviously—the VB programmer has attempted to set the TimeSpan t2 (a ValueType) to Nothing. The VB compiler doesn’t prohibit you from doing this, as the C# compiler would if that programmer had tried to set t2 = null.
Programmers at my company (other than me) do this constantly. The reason is that they got used to doing it to every object variable in VB6. Whether or not that was actually necessary, I don’t know. It’s beyond the scope of this post, anyway.
At any rate, it shouldn’t matter. At most, it should end up just being one instruction and might even get tossed out by the JIT compiler. Right? Wrong.
On average, the C# loop executes more than 5 times faster. Roughly 5 seconds for VB versus roughly one second for C# on my machine. When you remove the extra line in VB, the times are comparable. If we replace TimeSpan with a reference type but leave the extra line, the times are comparable.
Why? Looking at the MSIL generated when we have gives us this in Release mode:
; Equivalent to GetType(TimeSpan) L_001d: ldtoken [mscorlib]System.TimeSpan L_0022: call [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle([mscorlib]System.RuntimeTypeHandle) ; This is the late-binding way of creating an empty TimeSpan. L_0027: call object [mscorlib]System.Activator::CreateInstance([mscorlib]System.Type) L_002c: unbox [mscorlib]System.TimeSpan L_0031: ldobj [mscorlib]System.TimeSpan L_0036: stloc.2
Ok, so I can see now what the compiler is trying to do. Whereas the C# compiler would make us explicitly go looking for the TimeSpan.Zero field if we wanted to reset the value of a variable, the VB compiler is trying to help us out by creating an empty structure for us.
It would have saved us a little trouble, if that was at all what we were intending to do. In my case, it just happened because a cargo-cult programmer is used to typing it. Another problem is that it happens where, even understanding this behavior, you would still not expect it. Consider:
' Reminder - DictionaryEntry is a struct.
For Each entry As DictionaryEntry In hash
' ...
Next
This ends up being equivalent to setting entry = Nothing with each iteration. You’d therefore get the same late binding IL and this loop is many times slower than the “same” loop in C#.
I’m not a language or compiler designer, but here’s what I would like to see done (in order of preference).
- Disallow this with
Option Strict On, like C# does currently (a breaking change, obviously). - Give a compiler warning where it will happen.
- Do a better job of publicizing this kind of behavior. I can’t find any documentation on it.