How can I implement nested [] statements in C #?

Consider the class of nested arrays, each element can be either an array or a number:

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

Here is my attempt to implement the [] operator for it.

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

So the goal is to use it as shown below:

 MyArray arr = new MyArray(); ... do something with the array here ... int num = arr[3][5][1]; 

In the case of access to the "branch" and not the "leaf" (say, arr [3] [5] [1] has several elements), let it simply return 0, infinity or any integer is normal for us.

However, it is obvious that such nested statements will not work for my case, since the result of the statement is an object, not an instance of MyArray.

Currently, I see the only solution: define a conversion operator for int and make the [] operator always return only the element (which will be MyArray, unless we get an exception here). But is there any other way? Maybe using something like an IList interface might help? Or maybe there is a way to define several possible return types for a method in some way? (but so far I googled it is not possible, and there is no type in C #)

+4
source share
2 answers

Your statement should return MyArray . In addition, you must implement the implicit conversion operator from MyArray to 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; } } 

The problem is that the MyArray structure is not homogeneous: the compiler cannot know what it is going to get from the [] operator, but you must specify the exact type.

One option would be to use dynamic in the return, but its use is associated with significant performance penalties.

+4
source

What you represent is a logical data structure such as a tree, you just want to use an indexer to access the elements (this is good if you tend to know the structure of the tree at compile time).

Typically, a composite template is used with tree data structures. You have an interface that defines a node, and then two types of classes that implement it; one for leaves and one for parent nodes. The node interface has a certain number (or set) of other nodes (which can be either an implementation, or it can be an empty collection if it is a node leaf).

Here is a slightly simpler implementation that does not use interfaces; it's not exactly as reliable (it relies more on conventions to tell you what's going on), but the concept is the same:

 public class Node { private List<Node> children = new List<Node>(); /// <summary> /// This will have a non-null value if it a leaf. It will be null if it 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]; } } } 
0
source

All Articles