現在ログインしていません。
新規アカウント作成
ログイン

文字列型の列挙体

列挙体数値型と決まっていて、文字列型の列挙体は作成できません。

しかし、コーディング中に列挙体のように選択肢として提供される文字列は定義可能です。その方法を紹介します。

実現されるのは次のような動作です。CompletionList

BloodType型は独自に定義した構造体です。 注目すべきはこのBloodType型に値を代入しようとして時に選択肢が提供されていることです。 そして、この独自の構造体を直接文字列に代入したり、逆に文字列を構造体に直接代入することもできます。

Dim bloodType As BloodType = BloodType.AB
Dim strValue As String = bloodType
■リスト1:VB 構造体と文字列の直接代入

なお、この手法はVBC#の両方で使えますが、C#の場合、もともと列挙体でも初期状態では選択肢が展開されてない状態でインテリセンスが表示されるのでありがたみが少ないです。

構造体に選択肢を提供する

構造体に選択肢を提供するにはcompletionlistコメントを使用します。 驚くべきことに、この動作は属性やデザイナークラスの機能で定義されるのではなく、コメントで定義されます。

''' <summary>赤血球の表面の抗原の型を表します。</summary>
''' <completionlist cref="BloodType"/>
Public Structure BloodType

    ''' <summary>A抗原のみ現出</summary>
    Public Shared Property A As New BloodType("A")

    ''' <summary>B抗原のみ現出</summary>
    Public Shared Property B As New BloodType("B")

    ''' <summary>A抗原とB抗原の両方が現出</summary>
    Public Shared Property AB As New BloodType("AB")

    ''' <summary>A抗原もB抗原もどちらも現出していない</summary>
    Public Shared Property O As New BloodType("O")

    Private rawValue As String

    Public Sub New(rawValue As String)
        Me.rawValue = rawValue
    End Sub

End Structure
■リスト2:VB 選択肢のある構造体

/// <summary>赤血球の表面の抗原の型を表します。</summary>
/// <completionlist cref="BloodType"/>
public struct BloodType
{

    /// <summary>A抗原のみ現出</summary>
    public static BloodType A { get; set; } = new BloodType("A");

    /// <summary>B抗原のみ現出</summary>
    public static BloodType B { get; set; } = new BloodType("B");

    /// <summary>A抗原とB抗原の両方が現出</summary>
    public static BloodType AB { get; set; } = new BloodType("AB");

    /// <summary>A抗原もB抗原もどちらも現出していない</summary>
    public static BloodType O { get; set; } = new BloodType("O");

    private string rawValue;

    public BloodType(string rawValue)
    {
        this.rawValue = rawValue;
    }
 }
■リスト3:C# 選択肢のある構造体

completionlistコメントの crefに設定したクラスの静的プロパティ(VBだとShared、C#だとstatic)が表示される選択肢になります。

他のクラスを巻き込むと話が面倒になるので、自分自身を指定するのが一番シンプルです。 そして、自分自身の静的プロパティとして選択肢を定義しておきます。

これで選択肢付きの構造体は完成です。 内部で保持する値は文字列でなくても何でもよいですが、次に説明する文字列の直接代入を実現するには文字列が最も簡単です。

文字列の直接代入

独自の型(上記の場合はBloodType)と文字列を直接代入できるようにするにはVBの場合はCType演算子を、C#の場合はキャストオーバーロードします。 本来同じ意味でない型は直接代入できるようにすべきではないので、うまく活用する自身がなければこの手法は使わないでください。

さきほどのBloodType構造体に下記のメンバーを追加すると実現できます。 この例ではWidening(C#ではimplicit)を指定して、変換が行われていることを隠蔽するようにしています。

Public Shared Widening Operator CType(value As BloodTypeAs String
    Return value.rawValue
End Operator

Public Shared Widening Operator CType(value As StringAs BloodType
    Return New BloodType(value)
End Operator
■リスト4:VB 文字列との直接代入を可能にする

public static implicit operator string(BloodType value)
{
    return value.rawValue;
}

public static implicit operator BloodType(string value)
{
    return new BloodType(value);
}
■リスト5:C# 文字列との直接代入を可能にする