Bitwise comparisons with Classes and Enums.

May 04, 2021

Comparing variables using bitwise operators

About bitwise comparison operators

This is the third and final post in a mini-series. Part one covered Enums and part 2 covered Classes, skip back to those if you arent comfortable with exactly what they do for a PowerShell script.

Using bitwise operators to compare objects

Enums as described in part one of this series have another benefit to us, if we are up to doing some comparisons using binary operators. They allow for compact storage of yes/no options. Continuing to use our example object, TVs have a lot of features nowadays so it could be really handy to keep all features in one property rather than adding hundreds of individual properties to our object. We need to set up an enum with each of our features first and the add a Features property to our class.

[flags()]enum TVFeature{
    HDMIInput = 1
    SmartTV = 2
    USB = 4
    TVGuide = 8
    WallMount = 16
    UHD = 32
}

Class Television4 {
    [string]$Manufacturer
    [string]$Model
    [TVFeature]$Features

    [string]ToString() {
        return ("The {0} {1} has these features: {2}" -f $this.Manufacturer, $this.Model, $this.Features)
    }
}

Notice the slight twist to the enum declaration - it has a [flags] prefix and the label values rise as a power of two (More details).

# define a new object of our latest type of TV
$TV = [television4]::new()
# set some basic property values
$TV.Manufacturer = 'Panasonic'
$tv.Model = "P9000"

# check out the object
$tv

image

# so lets confirm we have HDMIInout for this TV
$tv.Features = [tvfeature]::HDMIInput

$tv

image

# but what if we also have one of the other features as well ?
$tv.Features += [tvfeature]::UHD

$tv

image

# calling the ToString method gets all of the object properties in the string format that we specified 
$tv.ToString()

image

It’s pretty trivial to add or remove features to our objects using += and -=.

# adding and removing features is simple with += and -=
$tv.Features += [TVFeature]::SmartTV
$tv.Features += [TVFeature]::USB
$tv.Features -= [TVFeature]::HDMIInput

# check out our TV object now
$tv; $tv.ToString()

image image

Does this help us tell what features a TV has?

Great question - yes it does! We need to start using lesser known bitwise comparison operators -band and -bnot to do this. We will take a look at -band first this does a bitwise comparison on two objects and returns true if the comparison is equivalent. As help says:

“In a bitwise AND operation, the resulting bit is set to 1 only when both input bits are 1.”

# using -band to find features
$tv.Features -band [tvfeature]::HDMIInput

$tv.Features -band [tvfeature]::SmartTV

image

if ($tv.Features -band [tvfeature]::SmartTV) {
    "This TV has SmartTV feature"
}

image

switch ($tv.Features) {
    { $_ -band [TVFeature]::HDMIInput } { "We have HDMIInput feature" }
    { $_ -band [tvfeature]::SmartTV } { "We have SmartTV feature" }
    { $_ -band [tvfeature]::USB } { "We have USB feature" }
    { $_ -band [tvfeature]::TVGuide } { "We have TVGuide feature" }
    { $_ -band [tvfeature]::WallMount } { "We have WallMount feature" }
    { $_ -band [tvfeature]::UHD } { "We have UHD feature" }
}

Making use of the switch operators feature of evaluating all comparisons regardless of making a match in any we can get this output image

With some crafty bitwise comparisons we can use our script to check which TVs hve what features and are therefore ones to consider buying.

# want to buy a TV with 'this' or 'that' feature?
# is we want a TV that has UHD and TVGuide or SmartTV
if (($tv.Features -band [tvfeature]::UHD) -band (($tv.Features -band [tvfeature]::TVGuide) -bor ($tv.Features -band [tvfeature]::SmartTV))) {
    Write-Output ("The {0} TV has the features you want" -f ($tv.Manufacturer))
}
else {
    Write-Output ("Sadly the {0} TV doesnt have the features you want" -f ($tv.Manufacturer))
}

image

With all the features in one property it is very simple to add a lot of them in one update to the object

# want to add multiple features at once?
# Lets get a new TV

# define a new object of our lagest type of TV
$TV = [television4]::new()
# set some basic property values
$TV.Manufacturer = 'LG'
$TV.Model = "HAL100"

# what do we get if we add enums together?
[int]([TVFeature]::SmartTV + [TVFeature]::UHD)

image

#can we set the TV Features like that?
$tv.Features = 34

$TV.Features

image

So there we have it, Enums, Classes and Bitwise comparison operators. I hope you found something in this series of posts thats useful to you.

Further reading

about enum about classes arithmetic operators