2014年6月21日

構造体(struct)で再帰的定義

.NET の構造体は、自身をプロパティとして持つことはできない。(クラスなら可能)
理由は単純で、構造体は値型で null にならないため、構造体のサイズが無限になってしまうためである。
(自身をプロパティに持つと、そのプロパティがさらに自身をプロパティとして持ち・・・と無限に続く)

// 自身をプロパティとして持つ例
// ※コンパイルエラーになる
struct Node
{
    public int Value;
    public Node Next;
}

代替案1 クラス

構造体の代わりにクラスを使う。
クラスは null になるため、再帰的定義が可能。

class Node
{
    public int Value;
    public Node Next;
}

代替案2 構造体ポインタ

どうしても構造体を使いたい場合、unsafe でプロパティを構造体のポインタを型とする。
ポインタだと null になれるので、構造体のサイズが無限になることもない。
ただし、unsafe が必要なのでコードが汚くなる。
unsafe が使えない VB.NET では不可。

unsafe struct Node
{
    public int Value;
    public Node* Next;
}

static class Program
{
    static void Main()
    {
        // 使用例
        var node = new Node() { Value = 1 };
        unsafe {
            node.Next = &node;
            Console.WriteLine(node.Value); // 1
            Console.WriteLine(node.Next->Value); // 1
            Console.WriteLine(node.Next->Next->Value); // 1
        }
    }
}

上記例で構造体ポインタをプロパティで隠せばいいかも、と思うかもしれないが無理。
C# のプロパティは参照渡し不可。

0 件のコメント:

コメントを投稿