列挙型

前々回と前回でデータを格納する方法として配列とハッシュテーブルについて取り上げた。今回はデータを格納する目的ではないが、PowerShell Coreでスクリプトを作成するにあたって重要になってくる列挙型について取り上げる。

列挙型はプログラミングをしたことがない場合には存在意義がよくわからない機能のひとつだろう。しかし、これは実に便利な機能である。たとえば次はC言語で列挙型を使って新しい型を定義したコードだが、こうした定義を行うことで意味づけが明確になってソースコードが読みやすくなる。

C言語における列挙型の使用例

typedef enum __element_type {
        TYPE_STRUCTURE,
        TYPE_KEY,
        TYPE_VALUE,
        TYPE_NOT_APPLICABLE
} ELEMENT_TYPE;

typedef enum __element {
        ELEMENT_DOCUMENT,
        ELEMENT_DOCGROUP,
        ELEMENT_DOCINFO,
        ELEMENT_TITLE,
        ELEMENT_AUTHOR,
        ELEMENT_FIRSTEDITION,
        ELEMENT_LASTMODIFIED,
        ELEMENT_P,
        ELEMENT_NOT_APPLICABLE
} ELEMENT;

typedef struct __element_info {
        ELEMENT_TYPE    element_type;
        ELEMENT         element;
        char*           name;
} ELEMENT_INFO;

C言語の場合、列挙型は整数に置き換わるため、その存在意義がよくわからないことがある。しかし、列挙型として記述することでマクロや整数として直接記述した場合と比べて、意味的なまとまりがわかりやすくなる。コーディングしながらデータを定義する場合にも利用でき、なかなか便利な機能である。列挙型を見ることでどういったことを想定したソースコードなのかも推測しやすくなる。

上記コードでELEMENTとして定義されている列挙型をPowerShell Coreで書くと次のようになる。書き方はとてもシンプルだ。

PowerShell Coreにおける列挙型の定義例

enum ELEMENT {
    DOCGROUP
    DOCINFO
    TITLE
    AUTHOR
    FIRSTEDITION
    LASTMODIFIED
    P
    NOT_APPLICABLE
}

列挙型はif制御構文やswitch制御構文で利用することが多いように思う。たとえば列挙型を定義して利用するPowerShell Coreのダミーコードを書くとすれば次のようになる。

列挙型を使ったコーディングの例

enum ELEMENT {
    DOCGROUP
    DOCINFO
    TITLE
    AUTHOR
    FIRSTEDITION
    LASTMODIFIED
    P
    NOT_APPLICABLE
}

$ele = [ELEMENT]::P

switch ($ele) {
    DOCGROUP {
        Write-Output "DOCGROUP"
    }
    DOCINFO {
        Write-Output "DOCINFO"
    }
    TITLE {
        Write-Output "TITLE"
    }
    AUTHOR {
        Write-Output "AUTHOR"
    }
    FIRSTEDITION {
        Write-Output "FIRSTEDITION"
    }
    ASTMODIFIED {
        Write-Output "LASTMODIFIED"
    }
    P {
        Write-Output "P"
    }
    default {
        Write-Output "NO SUCH ELEMENT"
    }
}

if制御構文の使い方やswtich制御構文の使い方は、今後連載の中で取り上げる予定で、詳細はそのときに解説する。ここではこのように書くことができる、ということを覚えておいてもらえればよい。

列挙型の利用例

PowerShell Coreのプロンプトからインタラクティブにコードを入力しながら列挙型を使ってみよう。まず、次のようにELEMENTという列挙型を作成してみる。

ELEMENTという列挙型を作成

PS /Users/daichi> enum ELEMENT {
>> DOCGROUP
>> DOCINFO
>> TITLE
>> AUTHOR
>> FIRSTEDITION
>> LASTMODIFIED
>> P
>> NOT_APPLICABLE
>> }
PS /Users/daichi>

ELEMENTという列挙型にはDOCGROUP、DOCINFO、TITLE、AUTHOR、FIRSTEDITION、LASTMODIFIED、P、NOT_APPLICABLEという識別子が定義されている。列挙型は[列挙型名]といった記述でアクセスできるようになっており、.GetEnumNames()というメソッドを叩けば、定義されている識別子を一覧表示できる。次のような感じだ。

列挙型の識別子を一覧表示する.GetEnumNames()メソッド

PS /Users/daichi> [ELEMENT].GetEnumNames()
DOCGROUP
DOCINFO
TITLE
AUTHOR
FIRSTEDITION
LASTMODIFIED
P
NOT_APPLICABLE
PS /Users/daichi>

PowerShell Coreの列挙型における識別子は番号を指定しなかった場合、基本的には0からインクリメントしていく整数に対応するようになる。次のように列挙型の識別子を[int]でキャストして表示させると確認することができる。

列挙型の識別子は指定がなければ0からのインクリメント整数に割り当てられる

PS /Users/daichi> [int][ELEMENT]::DOCGROUP
0
PS /Users/daichi> [int][ELEMENT]::DOCINFO
1
PS /Users/daichi> [int][ELEMENT]::TITLE
2
PS /Users/daichi> [int][ELEMENT]::AUTHOR
3
PS /Users/daichi> [int][ELEMENT]::FIRSTEDITION
4
PS /Users/daichi> [int][ELEMENT]::LASTMODIFIED
5
PS /Users/daichi> [int][ELEMENT]::P
6
PS /Users/daichi> [int][ELEMENT]::NOT_APPLICABLE
7
PS /Users/daichi>

列挙型の.GetEnumName()メソッドにはこの整数を指定することで対応する識別子にアクセスできるようになっている。

整数から識別子にアクセスする.GetEnumName()メソッド

PS /Users/daichi> [ELEMENT].GetEnumName(0)
DOCGROUP
PS /Users/daichi> [ELEMENT].GetEnumName(1)
DOCINFO
PS /Users/daichi> [ELEMENT].GetEnumName(2)
TITLE
PS /Users/daichi> [ELEMENT].GetEnumName(3)
AUTHOR
PS /Users/daichi> [ELEMENT].GetEnumName(4)
FIRSTEDITION
PS /Users/daichi> [ELEMENT].GetEnumName(5)
LASTMODIFIED
PS /Users/daichi> [ELEMENT].GetEnumName(6)
P
PS /Users/daichi> [ELEMENT].GetEnumName(7)
NOT_APPLICABLE
PS /Users/daichi>

if制御構文で定義された列挙型を利用するとすれば、たとえば次のように利用することになる。

列挙型の使用例

 /Users/daichi> $ele = [ELEMENT]::P
 PS /Users/daichi> if ($ele -eq [ELEMENT]::DOCGROUP) { "docgroup" }
 PS /Users/daichi> if ($ele -eq [ELEMENT]::DOCINFO) { "docinfo" }
 PS /Users/daichi> if ($ele -eq [ELEMENT]::P) { "p" }
 p
 PS /Users/daichi>

本連載ではまだPowerShell Coreの制御構文については取り上げていないので深くは説明しないが、列挙型を利用することで制御構文、特にifやswitchで分岐処理を記述する場合にソースコードの可読性を向上させることができる。

このあたりの機能は実際にコーディングしていないとわからない利便性なのだが、今は列挙型を使うといろいろ便利だ、ということを覚えておいてほしい。

参考資料