講座全体の概要
プログラミング基礎講座の番外編です。プログラミングをする上でぜひ覚えておきたい、Enumというものについて解説します。講座全体の概要は以下の記事ゼロから始めるプログラミング基礎講座 第1回【講座の概要・目的】をご覧ください。
Enum(列挙型)とは
Enum(読み方はイーナムが一般的)とは、複数の定数を列挙したものをまとめて一つの型として扱えるようにしたものです。列挙型ともいわれます。
この説明だけではわからないと思いますので、以下で具体的例を見ながら解説していきます。
Enumの定義方法
まず、Enumの定義方法から見ていきます。
namespace BasicCourseEx.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public string Message1 { get; set; }
public string Message2 { get; set; }
public void OnGet()
{
Message1 = GetMessage1(Month.Jun);
int i = 10;
Message2 = GetMessage2(3);
}
private string GetMessage1(Month monthEnum)
{
return monthEnum + " は" + (int)monthEnum + "月です。";
}
private string GetMessage2(int monthNumber)
{
return monthNumber + "月は " + (Month)monthNumber + " です。";
}
public string GetSample(SampleKind kind)
{
if (kind == SampleKind.A)
{
return "Aタイプの処理結果";
}
else if (kind == SampleKind.B)
{
return "Bタイプの処理結果";
}
else if (kind == SampleKind.C)
{
return "Cタイプの処理結果";
} else
{
return "ありえない";
}
}
public enum SampleKind
{
A,
B,
C
}
}
}
public enum Month
{
Jan = 1,
Feb,
Mar,
Apr,
May,
Jun,
Jul,
Aug,
Sep,
Oct,
Nov,
Dec
}
この例では以下の部分でMonthという名前のEnumを定義しています。このようにクラススコープの外で定義することで、どこからでも直接参照できるようになります。対して、このクラスのメソッドを使用する時だけ必要なEnumは、上記例の「SampleKind」の様にクラススコープ内に記述し、クラスのメンバーとします。
public enum Month
{
Jan = 1,
Feb,
Mar,
Apr,
May,
Jun,
Jul,
Aug,
Sep,
Oct,
Nov,
Dec
}
構文は以下の通りです。
public enum 列挙型の名前[ : 定数の型]
{
定数1の名前[ = 定数1の値],
・
・
・
定数nの名前[ = 定数nの値]
}
定数の型を省略すると、int型となります。その他に指定できる定数の型は整数型のみです。Java等の言語では整数型以外を定数として扱えるものもあります。
定数はカンマ区切りで複数記述できます。定数の値を省略した場合は、記述された定数の順に、0から始まる連番が振られます。定数の値を明示することで、連番ではない値を設定することも可能です。
一部の定数にだけ値を明示した場合、それより後の定数に値を明示しない限りは、明示した値から始まる連番が振られます。
今回の例では、最初の定数に1を設定し、後を省略することで、1から12の連番を振っています。
Enumをメソッドの引数の型として扱う
列挙型の名前は型として扱えます。以下の部分ではメソッドの引数の型として列挙型の名前「Month」を指定しています。
private string GetMessage1(Month monthEnum)
{
return monthEnum + " は" + (int)monthEnum + "月です。";
}
このメソッドの呼び出し側では、以下の様にしてMonthに列挙されている定数のいずれかを指定します。列挙された定数以外は指定できません。定数の値であるint型の数値も指定はできません。
public void OnGet()
{
Message1 = GetMessage1(Month.Jun);
}
引数の型としてEnumを使用することで、呼び出し側から想定外の値を引数として渡されることを防ぐことができます。加えて、Enumの名前と定数名により、引数の値が何を意味するかが明確になります。何らかの種類を表すような場合に、int型やstring型ではなく、専用のEnumを定義することで呼び出し側と、呼び出される側で値の意味を取り違えることもなくなります。
Enumに列挙された定数の使用方法
Enumの定数を参照して得られる値を確認しましょう。上記のEnumの具体例と併せて以下のコードを実装し、デバッグ実行して動作を確認してください。
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Enumの例</h1>
<p>@Model.Message1</p>
<p>@Model.Message2</p>
<p>Enumの参照:@Month.Jul</p>
<p>Enumの参照(値):@((int)Month.Jul)</p>
<p>クラススコープ内のEnum参照:@Model.GetSample(IndexModel.SampleKind.A)</p>
</div>
定数を参照すると、通常はその定数の名前がそのまま文字列として取得されます。定数の値を取得したい場合は、int型へキャスト(型変換)することで可能です。
キャストは(キャスト後の型)キャストしたい変数等の様に記述します。
今回の例では以下の部分でキャストして定数の値を取得しています。
private string GetMessage1(Month monthEnum)
{
return monthEnum + " は" + (int)monthEnum + "月です。";
}
<p>Enumの参照(値):@((int)Month.Jul)</p>
「Index.cshtml」では@( )の中に(int)Month.Julを記述していることに注意してください。
@はその後ろがC#のコードであることを表す記号ですが、@(int)Month.Julと記述するとエラーになってしまいます。
実は@の直後に記述した(は、その後に記述したC#のコードの範囲が)までであることを明示するための特別な意味を持ちます。@( )でC#のコードを囲むことで、後ろにHTMLの記述が続く場合にも、囲まれた部分だけをC#のコードとして正しく解釈させることができます。
しかし、今回はキャストのための(int)がC#コードの先頭にあります。このため、@(int)Month.Julと記述すると、@( )に囲まれた部分intだけがC#のコードとして解釈されてしまいます。これを避けるために@( )で範囲を明示して、その中に(int)Month.Julを記述することでエラーを避けています。
クラスメンバーのEnumを使用する
以下の部分ではIndexModelクラスのメンバーのSampleKindを使用しています。
public string GetSample(SampleKind kind)
{
if (kind == SampleKind.A)
{
return "Aタイプの処理結果";
}
else if (kind == SampleKind.B)
{
return "Bタイプの処理結果";
}
else if (kind == SampleKind.C)
{
return "Cタイプの処理結果";
} else
{
return "ありえない";
}
}
<p>クラススコープ内のEnum参照:@Model.GetSample(IndexModel.SampleKind.A)</p>
SampleKindを定義しているIndexModelクラス自身では「SampleKind」を直接指定できますが、Index.cshtmlでは「IndexModel.SampleKind」と指定しています。この様に、定義されているクラス以外からクラスメンバーのEnumや定数を使用する場合は、クラス名.メンバーとする必要があります。
また、IndexModelクラスのパブリックメソッドは、プロパティの参照と同じ様に@Model.メソッド名()とすればIndex.cshtmlで使用することが可能です。
次回はエラー処理
Enumの説明は以上です。次回はエラー処理について解説します。
この記事へのコメントはありません。