如何在C#中实现嵌套的[]运算符?

时间:2012-11-29 15:53:47

标签: c# oop

考虑一类嵌套数组,每个元素可以是数组或数字:

[[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#中没有任何一种类型)

2 个答案:

答案 0 :(得分:4)

您的运营商应该返回MyArray。此外,您应该实现MyArrayint的隐式转换运算符:

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的结构不是同质的:编译器无法知道从[]运算符得到什么,但是你必须指定确切的类型。

另一种选择是在回报中使用dynamic,但其使用会带来重大的性能损失。

答案 1 :(得分:0)

您所代表的是一种逻辑“树”类型的数据结构,您只需要使用索引器来访问元素(如果您在编译时倾向于知道树的结构,那就很好了。) / p>

通常使用基于树的数据结构,复合模式是适用的。您有一个定义节点的接口,然后是两种实现它的类;一个用于叶子,一个用于父节点。然后,节点接口具有一些(或集合)其他节点(可以是实现,也可以是空集合,如果它是叶节点)。

这是一个稍微简单的实现,不使用接口;它不是那么强大(它更多地依赖于约定来告诉你发生了什么),但概念是相同的:

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];
        }
    }
}