4

ネストされた配列のクラスを考えてみましょう。各要素は配列または数値のいずれかになります。

[[1, 2, [3, 4, [5]], [6, 7]], 8]

[] 演算子を実装しようとする私の試みは次のとおりです。

class MyArray {

    List<MyArray> elements;
    int value;

    public object this[int index] {
        get {
            if (elements.Count > 0) {
                return elements;
            } else {
                return value;
            }
        }
    }

}

したがって、目標は次のように使用することです。

MyArray arr = new MyArray();

... do something with the array here ...

int num = arr[3][5][1];

「リーフ」で​​はなく「ブランチ」にアクセスする場合 (たとえば、arr[3][5][1] には複数の要素があります)、0、無限大、または任意の整数を返します。

ただし、明らかに、演算子の結果は MyArray インスタンスではなくオブジェクトであるため、このようなネストされた演算子は私の場合には機能しません。

現時点では、唯一の解決策があります。変換演算子を int に定義し、[] 演算子が常に要素のみを返すようにします (ここで例外が発生しない場合、これは MyArray になります)。しかし、他の方法はありますか?たぶん、IList インターフェイスのようなものを使用すると役立つでしょうか? または、何らかの方法でメソッドに対して複数の可能な戻り値の型を定義する方法があるでしょうか? (しかし、これまでグーグルで検索したところ、それは不可能であり、C#にはどちらの型もありません)

4

2 に答える 2

4

オペレーターが戻ってくるはずMyArrayです。さらに、 to の暗黙的な変換演算子を実装する必要がありMyArrayますint

class MyArray {

    List<MyArray> elements;
    int value;

    public MyArray this[int index] {
        get {
            return elements[index];
        }
    }
    public static implicit operator int(MyArray d) {
        return d.value;
    }
}

問題は、 の構造が均一でないことです。コンパイラは、演算子MyArrayから何を取得しようとしているのかを知ることができませんが、正確な型を指定する必要があります。[]

代替手段の 1 つdynamicは、return で使用することですが、これを使用すると、パフォーマンスが大幅に低下します。

于 2012-11-29T15:55:53.573 に答える
0

あなたが表しているのは、論理的な「ツリー」タイプのデータ構造です。単にインデクサーを使用して要素にアクセスしたいだけです (コンパイル時にツリーの構造を知っている傾向がある場合はこれで問題ありません)。

通常、ツリー ベースのデータ構造では、複合パターンが適用されます。ノードを定義するインターフェースと、それを実装する 2 種類のクラスがあります。1 つはリーフ用、もう 1 つは親ノード用です。次に、ノード インターフェイスには、いくつかの (またはコレクションの) 他のノードがあります (実装である場合もあれば、リーフ ノードの場合は空のコレクションである場合もあります)。

これは、インターフェースを使用しないやや単純な実装です。それほど堅牢ではありません (何が起こっているかを伝えるために規則に依存しています) が、概念は同じです:

public class Node
{
    private List<Node> children = new List<Node>();

    /// <summary>
    /// This will have a non-null value if it's a leaf.  It will be null if it's not a leaf.
    /// </summary>
    public int? Value { get; set; } 

    public Node this[int index]
    {
        get
        {
            if (children.Count == 0)
            {
                throw new ArgumentException("This node has no children");
            }
            if (children.Count > index)
            {
                throw new ArgumentException("This node doesn't have that many children");
            }

            return children[index];
        }
    }
}
于 2012-11-29T16:21:37.927 に答える