PowerShell Cookbook

Twitter Updates

    follow me on Twitter

    Search

    Categories

     

    On this page

    PowerShell's -EQ Operator: Reference Equality vs Value Equality

    Archive

    Blogroll

    Disclaimer
    I work for Microsoft.

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    RSS 2.0 | Atom 1.0 | CDF

    Send mail to the author(s) E-mail

    Total Posts: 235
    This Year: 12
    This Month: 0
    This Week: 0
    Comments: 634

    Sign In

     Wednesday, December 05, 2007
    Wednesday, December 05, 2007 5:43:41 PM (Pacific Standard Time, UTC-08:00) ( )

    A question recently came up asking why the -eq operator doesn't work for two different (but equal) SecureStrings.

     

    By default, almost all environments (the .NET Framework included) test if two things are exactly the same – that they are stored in the same place in memory. This is called reference equality.

     

    [D:\documents\WindowsPowerShell]

    PS:14 > $test = Read-Host -AsSecureString

    ****

     

    [D:\documents\WindowsPowerShell]

    PS:15 > [Object]::ReferenceEquals($test, $test)

    True

     

    [D:\documents\WindowsPowerShell]

    PS:16 > $test -eq $test

    True

     

    That’s not usually what people want, so each individual type of object is (optionally) responsible for supporting a value-based equality test. They do this by implementing interfaces (software contracts) called IComparable and / or IEquatable:

     

    [D:\documents\WindowsPowerShell]

    PS:17 > $string1 = "Test"

     

    [D:\documents\WindowsPowerShell]

    PS:18 > $string2 = "Test"

     

    [D:\documents\WindowsPowerShell]

    PS:19 > [Object]::ReferenceEquals($string1, $string2)

    False

     

    [D:\documents\WindowsPowerShell]

    PS:20 > [String].GetInterfaces()

     

    IsPublic IsSerial Name

    -------- -------- ----

    True     False    IComparable

    True     False    ICloneable

    True     False    IConvertible

    True     False    IComparable`1

    True     False    IEnumerable`1

    True     False    IEnumerable

    True     False    IEquatable`1

     

    [D:\documents\WindowsPowerShell]

    PS:21 > $string1 -eq $string2

    True

     

     

    The implementors of the SecureString class have chosen to not implement these contracts, so PowerShell supports only reference equality on these types:

     

    [D:\documents\WindowsPowerShell]

    PS:30 > [System.Security.SecureString].GetInterfaces()

     

    IsPublic IsSerial Name

    -------- -------- ----

    True     False    IDisposable

     

    [D:\documents\WindowsPowerShell]

    PS:31 > $test1 = Read-Host -AsSecureString

    ****

     

    [D:\documents\WindowsPowerShell]

    PS:32 > $test2 = Read-Host -AsSecureString

    ****

     

    [D:\documents\WindowsPowerShell]

    PS:33 > $test1 -eq $test2

    False

     

    Comments [0] | | #