Monday, January 12, 2009

Comparing Nullable(of T) Values

Okay, I spent a good half hour earlier today slamming my head against the wall, trying to figure something out. Why my checkboxes in my tri-state tree were not getting set to the correct state based on user input.

What this is, is each checkbox on the tree has three possible checked states: true, false and indeterminate.

I had some rules going into this:

  1. A checkbox's state is the summation of its children's state (if all children are TRUE, then it is TRUE).
  2. A checkbox is indeterminate when any of its children are not in the same state as itself.
  3. If a Checkbox's Parent is set to TRUE or FALSE, then the Checkbox shall be set to the same
Pretty straightforward if you ask me, and the state was being controlled by a nullable boolean (which is declared DIM _isChecked as Nullable(of Boolean) in VB or Boolean? _isChecked in C#).

Now, I'm using VB.Net for this, and when I only had a single set of children until you got to the lowest level, it all worked perfectly. I was happy and smiling. Well, today I shoved in extra children for every level that could have them, and got something... new for my troubles: only the first child was affecting the parent nodes, thus breaking rule 2, while modifying UP the tree.

Modifying down, still worked like a charm.

So, I'm off grumbling, and toss in a Breakpoint on the comparison operation. I mean, I see in the code where this value is supposed to be changed, and so that proverbial key to the kingdom is where I need to be looking.

I start up the application, get to the point in it where I use the tree, and uncheck something. the break point fires, and the promptly skips over the code, confused, I let it cycle back around as it verify's the parent's state.

Once I'm at the checkpoint again, I look to see what the result of the comparison operation is.

Only to discover, nothing.

Which means that the comparison did not fire, because their is no equilavencies between the two opposing states.

Frowning, I considered the implications of this, when suddenly I realized what was happening. A nullable boolean, has three possible values: True, False and NOTHING. The problem exists because NOTHING cannot be processed through a comparison operation such as "=" or, as I was using, "<>."

So, what was this poor programmer to do?

What I had forgotten, was the nullable objects have a "HasValue" property which returns a boolean based on if the variable is NOTHING or not.

Which means that, I had some fun coding to look forward to. Let's look at this, I had two values to check, both of them Nullable(of Booleans), which means I have this potential set of values:

Possible States
Value 1Value 2What I need to do
NNBoth Nullable Do Nothing
NTDifferent, Change
NFDifferent, Change
TNDifferent, Change
TTBoth True, Do Nothing
TFDifferent, Change
FNDifferent, Change
FTDifferent, Change
FFBoth False, Do Nothing

Where F=False, T=True, and N=Nothing. Those are all the potential states that I had to check for. Luckily, I had a few shortcuts for my logic:
  1. If they're both nothing, I don't have to do anything
  2. If one is nothing and the other Has a value, I HAVE to change
With those two logical operations in place (thanks to my handle state chart) I knew I only had to check for differences when both of my items had a value. Which in turns means that I ended up with an IF statement, which reads like:

One of these days, Blogger will support Code formatting, and I just won't know what to do. But I digress.

Now, if Microsoft had put a bit of FORETHOUGHT into their Nullable(of T) objects in VB.Net they would have provided inherent comparison operations between two instances of the Nullable(of T) objects. But that may be asking for a bit much I fear.

No comments:

Blog Widget by LinkWithin