One concept that is central to the understanding of the layout of classes in the Base Class Libraries is the Namespace.  Namespaces are a method of providing context for classes (and other constructs like Enums and Structs), allowing developers to group related classes and not worry about name collisions with development in other areas. In the Base Class Libraries, the root namespace is the System namespace.  The System namespace defines a large amount of the base types, like Object (which all classes derive from), String, DateTime, Boolean, and numerous others.  When you specify types, PowerShell can infer the “System” part.

Example:

PS C:\scripts\PowerShell> $random = New-Object –TypeName Random

is the same as

PS C:\scripts\PowerShell> $random = New-Object –TypeName System.Random

Namespaces are hierarchical, except in naming convention. The representation of a file in PowerShell is a great example.  A file object is represented in PowerShell as a System.IO.FileInfo object.  The FileInfo class lives in the System.IO namespace, which is a separate namespace than the System namespace.  There is a hierarchical impression implied, but that is solely through naming convention.

The CLR (Common Language Runtime) does not care about namespaces, only the fully qualified name of the class, so why use namespaces at all?

Namespaces are a convenience for developers, as languages like C# and VB.NET have language constructs that allow the developer to not have to use the fully qualified type name every time that is needed to be referenced.  C# provides the “using” syntax and VB.NET has the “imports” syntax.

How does this apply to PowerShell?

PowerShell does not currently have a “using” or “imports” syntax or language feature, but there are a couple of workarounds.  You can use variables holding the namespace and string concatenation to save some typing

PS C:\scripts\PowerShell> $netinfo = 'System.Net.NetworkInformation' PS C:\scripts\PowerShell> $ping = New-Object "$netinfo.ping" PS C:\scripts\PowerShell> $ping.gettype() IsPublic IsSerial Name           BaseType -------- -------- ----                -------- True     False    Ping            System.ComponentModel.Component

This doesn’t work with type accelerators though (at least in V1)..  V2 CTP3 has some other options and Oisin Grehan has a great discussion on how to find the type accelerators and add your own.

Another option would be to create a function to wrap the creation of objects for particular namespaces.

Use-Namespace is a function I came up with to create a function to wrap New-Object for specific namespaces.

The useage of Use-Namespace is PS C:\scripts\PowerShell>Use-Namespace System.IO, System.Net PS C:\scripts\PowerShell>$memorystream = New-System.IOObject MemoryStream PS C:\scripts\PowerShell>$memorystream.GetType() PS C:\scripts\PowerShell> $memorystream.gettype() IsPublic IsSerial  Name                    BaseType -------- --------   ----                         -------- True     True     MemoryStream      System.IO.Stream

And the function is here..

function Use-Namespace() {   param ([string[]]$Namespace)   BEGIN   {     if ($Namespace.length -gt 0)     {       $Namespace | Use-Namespace     }   }   PROCESS   {     if ($_ -ne $null)     {       $NS = $_       $NSObject = "$NS" + "Object"       $function = @" param ($Class, [string[]]$ArgumentList) if ($ArgumentList.length -gt 0) { return New-Object -TypeName "$NS.$Class" -ArgumentList $ArgumentList } else { return New-Object -TypeName "$NS.$Class" } "@     Set-Item -Path "function:global:New-$NSObject" -Value $function -force     Write-Debug "Created function:global:New-$NSObject "     }   } }

PSMDTAG:FAQ CLR PSMDTAG:FAQ Namespace PSMDTAG:FAQ .NET Framework

Want more great reading? Check out my reading list!