Search code examples
powershellreferencepowershell-2.0powershell-4.0

PowerShell: what is System.IO.StreamWriter and System.Diagnostics.ProcessStartInfo?


I'm learning PowerShell. With System.IO.StreamWriter and System.Diagnostics.ProcessStartInfo, is it more accurate to call them "Classes"? Or can they be referred to as "new-objects" as well?

$foo = New-Object System.Diagnostics.ProcessStartInfo

Solution

  • System.IO.StreamWriter and System.Diagnostics.ProcessStartInfo are classes, and more broadly types (or data types) in .NET

    PowerShell runs on .NET, and in .NET's type system a "class" is a blueprint for the behavior of what we call reference-type objects.

    $foo = New-Object System.Diagnostics.ProcessStartInfo
    

    In the statement above, we ask New-Object to create an instance of ProcessStartInfo - that is, we want an object that behaves as prescribed by the ProcessStartInfo class. We might also say that the resulting object (now referenced by $foo), is of type ProcessStartInfo.

    Reference types vs value types

    Above I referred to reference type objects. The reason this is important is that .NET types can be grouped into to kinds of types - reference types and value types.

    Value types are things like built-in numerical types ([int], [double], [decimal], [bool] etc.) - but also more complex data types like [datetime], the type of object returned by Get-Date.

    The reason this distinction (reference vs value) matter is that they act differently when assigned and stored. With value types, any assignment will cause .NET to copy the value of the object to the assignment target:

    $a = 1    
    $b = $a   # Assign value of $a to $b
    $a++      # Modify value of $a
    $b        # Is $b 1 or 2?
    

    During the assignment operation $b = $a, PowerShell looks at $a, sees that its value, 1, is of type [int] and stores a new copy of the value 1 in $b - so even though we increment the value of $a to 2, the value of $b is unchanged.

    With reference types, this is not the case. Reference types objects are stored and passed around by reference:

    $a = [System.Diagnostics.ProcessStartInfo]::new("calc.exe")
    $b = $a
    $a.FileName = "notreally.exe"
    $b.FileName             # Is $b.FileName "calc.exe" or "notreally.exe"?
    

    In this case, because [System.Diagnostics.ProcessStartInfo] is a reference type, $a doesn't contain the value (ie. the data associated with the object), it only contains a reference or a pointer to where the data is really stored in memory, and assigning $b = $a doesn't copy the object, instead both $a and $b ends up referencing the same underlying object, and modification of one is reflected when interrogated through the other.