PowerShellの型の話 (1) 型名とかタイプアクセラレータとか

*(2)があるかはわかりません。*

私自身詳細は把握できていないところもあるのですが、抱えている情報を吐き出しておこうと思いました。

誰かの書いたPowerShellのスクリプトを見た時、型名をなぜそのように記述できるのか疑問に思ったことは無いでしょうか。

#型の存在確認
PowerShellである型名が使えるかどうかは、`[(型名)]`を評価してみると分かります。

```:PowerShellコンソール
PS C:\> [int]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType
```
[int]は使えるようです。

```bat:PowerShellコンソール
PS C:\> [time]
型 [time] が見つかりません。この型を含むアセンブリが読み込まれていることを確認してください。
発生場所 行:1 文字:1
+ [time]
+ ~~~~~~
    + CategoryInfo          : InvalidOperation: (time:TypeName) []、RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

PS C:\> [datetime]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType
```
[time]はありません。
[datetime]はあるようです。

#型名の確認
型の完全修飾名を確認するには、FullNameプロパティを参照します。これはよく使います。

```bat:PowerShellコンソール
PS C:\> [datetime].FullName
System.DateTime
```
アセンブリ修飾名を確認するには、AssemblyQualifiedNameプロパティを参照します。あまり使いませんが、重要な情報も含まれています。

```bat:PowerShellコンソール
PS C:\> [datetime].AssemblyQualifiedName
System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
```

いずれの文字列も、PowerShellの型名として使えます。

```bat:PowerShellコンソール
PS C:\> [System.DateTime]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType


PS C:\> [System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType
```

#型名の省略記法について
型名記述の基本は、完全修飾名を記述する事です。(なおPowerShellでは大文字小文字の区別は不要です)
しかし完全修飾名は長くなりタイピングに不便な面もあり、ものによっては短く記述するためのサポートがあります。

##1. 「System.」の省略
完全修飾名から「System.」は常に省略して書くことができます。
なぜそう言えると判断するに至ったのかは既に覚えていないのですが・・・経験上これは確かなはずです！

例えば、Processクラスの完全修飾名は System.Diagnostics.Process ですが、PowerShellでは Diagnostics.Process と記述することができます。

```bat:PowerShellコンソール
PS C:\> [System.Diagnostics.Process]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Process                                  System.ComponentModel.Component


PS C:\> [Diagnostics.Process]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Process                                  System.ComponentModel.Component
```

##2. タイプアクセラレータ
タイプアクセラレータとは、型の別名です。型アクセラレータとも呼ばれます(…というか、むしろそちらが正統かもしれません)。
System.Int32 型を int と記述できるのは、このタイプアクセラレータが定義されているためです。

このタイプアクセラレータ定義の公式の仕様は不明ですが、下記のコマンドで一覧を確認することができます。

```ps1:PowerShellタイプアクセラレータ一覧
[psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get
```
PowerShellの内部実装にTypeAcceleratorsクラスがあります。このクラスは非Publicのため、AssemblyのGetTypeメソッドで取得する必要があります。その際TypeAccelerators の属するAssemblyオブジェクトを簡単に引っ張るためにpsobject型を利用しています。

この TypeAccelerators のGetプロパティ(static)が、タイプアクセラレータのDictionaryオブジェクトを返します。
私の環境では、結果は以下の様になりました。(PowerShell 4.0)

```:タイプアクセラレータ一覧(結果)
Key                    Value
---                    -----
Alias                  System.Management.Automation.AliasAttribute
AllowEmptyCollection   System.Management.Automation.AllowEmptyCollectionAttribute
AllowEmptyString       System.Management.Automation.AllowEmptyStringAttribute
AllowNull              System.Management.Automation.AllowNullAttribute
array                  System.Array
bool                   System.Boolean
byte                   System.Byte
char                   System.Char
CmdletBinding          System.Management.Automation.CmdletBindingAttribute
datetime               System.DateTime
decimal                System.Decimal
adsi                   System.DirectoryServices.DirectoryEntry
adsisearcher           System.DirectoryServices.DirectorySearcher
double                 System.Double
float                  System.Single
single                 System.Single
guid                   System.Guid
hashtable              System.Collections.Hashtable
int                    System.Int32
int32                  System.Int32
int16                  System.Int16
long                   System.Int64
int64                  System.Int64
wmiclass               System.Management.ManagementClass
wmi                    System.Management.ManagementObject
wmisearcher            System.Management.ManagementObjectSearcher
ciminstance            Microsoft.Management.Infrastructure.CimInstance
cimclass               Microsoft.Management.Infrastructure.CimClass
cimtype                Microsoft.Management.Infrastructure.CimType
cimconverter           Microsoft.Management.Infrastructure.CimConverter
NullString             System.Management.Automation.Language.NullString
OutputType             System.Management.Automation.OutputTypeAttribute
Parameter              System.Management.Automation.ParameterAttribute
pscredential           System.Management.Automation.PSCredential
PSDefaultValue         System.Management.Automation.PSDefaultValueAttribute
pslistmodifier         System.Management.Automation.PSListModifier
psobject               System.Management.Automation.PSObject
pscustomobject         System.Management.Automation.PSObject
psprimitivedictionary  System.Management.Automation.PSPrimitiveDictionary
ref                    System.Management.Automation.PSReference
PSTypeNameAttribute    System.Management.Automation.PSTypeNameAttribute
regex                  System.Text.RegularExpressions.Regex
sbyte                  System.SByte
string                 System.String
SupportsWildcards      System.Management.Automation.SupportsWildcardsAttribute
switch                 System.Management.Automation.SwitchParameter
cultureinfo            System.Globalization.CultureInfo
ipaddress              System.Net.IPAddress
mailaddress            System.Net.Mail.MailAddress
bigint                 System.Numerics.BigInteger
securestring           System.Security.SecureString
timespan               System.TimeSpan
uint16                 System.UInt16
uint32                 System.UInt32
uint64                 System.UInt64
uri                    System.Uri
ValidateCount          System.Management.Automation.ValidateCountAttribute
ValidateLength         System.Management.Automation.ValidateLengthAttribute
ValidateNotNull        System.Management.Automation.ValidateNotNullAttribute
ValidateNotNullOrEmpty System.Management.Automation.ValidateNotNullOrEmptyAttribute
ValidatePattern        System.Management.Automation.ValidatePatternAttribute
ValidateRange          System.Management.Automation.ValidateRangeAttribute
ValidateScript         System.Management.Automation.ValidateScriptAttribute
ValidateSet            System.Management.Automation.ValidateSetAttribute
version                System.Version
void                   System.Void
xml                    System.Xml.XmlDocument
scriptblock            System.Management.Automation.ScriptBlock
psvariable             System.Management.Automation.PSVariable
type                   System.Type
psmoduleinfo           System.Management.Automation.PSModuleInfo
powershell             System.Management.Automation.PowerShell
runspacefactory        System.Management.Automation.Runspaces.RunspaceFactory
runspace               System.Management.Automation.Runspaces.Runspace
initialsessionstate    System.Management.Automation.Runspaces.InitialSessionState
psscriptmethod         System.Management.Automation.PSScriptMethod
psscriptproperty       System.Management.Automation.PSScriptProperty
psnoteproperty         System.Management.Automation.PSNoteProperty
psaliasproperty        System.Management.Automation.PSAliasProperty
psvariableproperty     System.Management.Automation.PSVariableProperty
```

先に例示した datetime も、System.DateTime を定義したものであることが確認できます。
一覧に利用した psobject は、System.Management.Automation.PSObject ですね。

TypeAcceleratorsには、定義を追加するAdd/削除するRemoveメソッドもあります。

```text:タイプアクセラレータの追加と削除
PS C:\> [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Add('process','System.Diagnostics.Process')
PS C:\> [process]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Process                                  System.ComponentModel.Component


PS C:\> [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Remove('process')
True
PS C:\> [process]
型 [process] が見つかりません。この型を含むアセンブリが読み込まれていることを確認してください。
発生場所 行:1 文字:1
+ [process]
+ ~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (process:TypeName) []、RuntimeException
    + FullyQualifiedErrorId : TypeNotFound
```

## 補足
上記の型名省略が使用できるのは、PowerShellの文脈の範囲に限られます。
例えば、TypeクラスのGetTypeメソッドで型を取得する場合、パラメーターに指定する文字列に省略表記を使うことはできません。GetTypeに渡された文字列の処理は、PowerShellの処理の範囲外のためです。

まただいぶ外れますが、Add-Typeコマンドレットでアセンブリをロードする際、

```ps1:Add-Type例
Add-Type -AssemblyName System.Windows.Forms
```
等としますが、これは型名ではないので「System.」を省略できたりはしません。(…ちょっとできるかなと思ってしまったりするので一応)