Pass a boolean by reference and it loses its type?

I’ve caught this twice in action, but it seems to be very rare. I had a method where I passed a bool in by reference, and the bool got changed from true/false to 1/0 by something under the hood. My code only involved standard operators (!=, ==, etc) and true/false. From there on out, any equality tests or assignments do nothing to change the value back to true/false. It’s 1 or 0 and that’s just how it goes. No exceptions get thrown in any equality tests or assignments either. So this goes unnoticed until weird things happen. Then you have to catch it in debug mode by examining objects. I removed the “ref bool” variable and changed how the method works to fix the issue, but then the same thing happened in a different method with another “ref bool”.

I’ve caught this twice now over the past month in different spots in my code. True/False goes in and 1/0 comes out. I’ve had one of these code sections in place for 5 years, and I’ve never seen this behavior. I migrated to 4.3 and 4.3.8.1 in early fall. This code lives on a G120. I don’t think GHI has anything to do with this though. This seems like it has to be on the MS side.

I can’t share the code, but this doesn’t appear to be very repeatable anyways. And the code where it happened didn’t involve 1 or 0. It’s gotta be something heap-related that happens very rarely. I wanted to see if anyone has seen this before?

@ mmmtang - We haven’t seen this behavior ourselves and it is likely in the core interpreter code. If you can provide us with a minimal test case that reproduces it, we can take a look.

I just checked GIT, and I’ve seen this on a G120 and a G400. The code below is from a G400. I’ve got a settings screen that allows the user to turn time delayed features on/off with a directional input. The vast majority of the time there’s no issue whatsoever. But… once in a rare while _bTurnOn identifies as a 1 or 0 instead of a bool. It happens inside this function somehow. It’s true/false before the function and 1/0 inside the function and thereafter. I’m betting you could put this in a loop and never see it happen.

I don’t expect a fix/solution b/c this seems random (and due to MS). I’ve caught this in action several times now, and I just spent a day removing every “ref” variable I’ve got. I’ve only caught this on “ref bool”, but I don’t trust any of them now. If I can replicate it reliably, then I’ll post it, but I think the stars have to align just right. It’s bizarre. I just wanted to put this on your radar as something that has happened.

private TimeSpan UpdateFeature(TimeSpan _tsTime, bool _bIncrease, ref bool _bTurnOn)
{
    TimeSpan _tsReturnFeature = _tsTime;
    _bTurnOn = true;
   
    if (_bIncrease)
    {
        if (_tsTime == TimeSpan.MaxValue)
            _tsReturnFeature = Shared.ts15Sec;
        else if (_tsTime == Shared.ts15Sec)
            _tsReturnFeature = Shared.ts3Min;
        else if (_tsTime == Shared.ts3Min)
            _tsReturnFeature = Shared.ts4Min;
        else if (_tsTime == Shared.ts4Min)
            _tsReturnFeature = Shared.ts5Min;
        else if (_tsTime == Shared.ts5Min)
        {
            _tsReturnFeature = TimeSpan.MaxValue;
            _bTurnOn = false;
        }
    }
    else
    {
        if (_tsTime == Shared.ts5Min)
            _tsReturnFeature = Shared.ts4Min;
        else if (_tsTime == Shared.ts4Min)
            _tsReturnFeature = Shared.ts3Min;
        else if (_tsTime == Shared.ts3Min)
            _tsReturnFeature = Shared.ts15Sec;
        else if (_tsTime == Shared.ts15Sec)
        {
            _tsReturnFeature = TimeSpan.MaxValue;
            _bTurnOn = false;
        }
        else if (_tsTime == TimeSpan.MaxValue)
            _tsReturnFeature = Shared.ts5Min;
    }
    return _tsReturnFeature;
}

There is a lot of redefining what “true” and “false” mean, these days ???

When you say “_bTurnOn identifies as a 1 or 0 instead of a bool” (bleh Hungarian), what do you mean, exactly? How are you determining that?

You’re confusing a value (1 or 0) with a type (bool). In fact, under the covers, your variable is always a 1 or 0, but the way you’re phrasing it makes no sense, like “sometimes my fruit is a banana, and sometimes it’s running”. Doesn’t make sense.

I think he is saying that sometimes the Boolean is sometimes loosing its Boolean type.

There’s nothing wrong with Hungarian notation, and bananas can’t run. That’s just silly.

I caught this in action twice while debugging. I set a break point prior to this function. Prior to this function getting called, the bool that will be passed in as _bTurnOn is either true or false. This function gets called, _bTurnOn gets passed by reference, and now _bTurnOn becomes 0 or 1. There is no true or false for _bTurnOn anymore, only 0 or 1. _bTurnOn is a bool inside an object filled with other bools, ints, timespans, etc., and all of those have their correct type. I can examine this object in the debugger and I see a list of values like true, false, true, true, 0, true, true… but that 0 isn’t supposed to be a 0. It’s supposed to be a boolean. Somehow that bool is losing its type under the hood.

This is a fluke occurrence. I can’t repeat it reliably, and I can’t force it to happen. This code has evolved using netmf 4.2 for 4.5 years, and I finally moved to 4.3 recently. That’s when I started seeing some random behavior that didn’t make sense. I caught this bug in action a month or so ago in this function on a G400, and then I caught it a couple weeks ago on a G120 in a different product in a different function.

The only way I’ve seen this is happen is via a boolean passed by reference, and it happens very rarely. No, it doesn’t make sense.

I can’t guarantee that I saw this referenced bool turn to a 1. I know I saw it as a 0 in the debugger, but I don’t know if I saw it get assigned a 1. So, that might clarify something somewhere.

@ cyberh0me - I don’t have a screenshot of this happening. I have a witness, but not a screenshot. Doesn’t do me much good here, I know.

The weird behavior is in my product. It’s a remote control sending messages back and forth to something else. I had a bunch of these booleans passed by reference in my communications class, and I experienced some random disconnections and other weird behavior that is unexpected. I’m really hoping that the new weirdness is due to this rare glitch.

According to the CSharp Language Spec v5 that’s in my VS folder:
"No standard conversions exist between bool and other types. In particular, the bool type is distinct and separate from the integral types, and a bool value cannot be used in place of an integral value, and vice versa."
Yes, bool is a 1 or 0 under the hood, but it’s not an integral type.

Once _bTurnOn became 0 instead of true or false any assignment to the bool that was _bTurnOn didn’t matter. I had added an additional line after this function returned to set that boolean that _bTurnOn had represented, and it didn’t matter. Something like:
tsBlah = UpdateFeature(tsA, true, ref bSwitch);//in this function something bad happens to bSwitch

bSwitch = (tsBlah != TimeSpan.MaxValue);//at this point, bSwitch is 0 and not true or false
So, anything involving bSwitch being true isn’t happening. All the tests probably turn out false, but I can’t say for sure. Once I found the bug I stopped passing the bool by reference and changed the way the method works. I just stopped passing that bool b/c it wasn’t needed anymore anyways.

You’re almost certainly seeing an issue in the debugger. It’s not possible for a variable to change types, because under the covers, they’re just memory locations. It’s the compiler that assigns and enforces types, and your code wasn’t recompiled during debugging.

I hate to break it to you, but this “glitch” is almost certainly not the root cause of your issues.

It’s not like you could get a “VariableChangedToTheWrongTypeException”, because such a thing doesn’t exist, such a thing [em]cannot[/em] exist in a strongly-typed system. Even if the debugger is showing nonsense for the watch value, your code will continue to operate as expected.