views:

267

answers:

3

I'm building a tree-based data structure and overloaded [ ] so that I can say

node["key1", "key2", "key3"]

which returns the node whose parents 1, 2, and 3 levels above are the nodes with those keys. the nodes conceptually map to an array of data, so what I have now is this function:

node[keys...].SetValue(i, value)

which sets the i-th value in the node's data. what would be nice is if I could do this:

node[keys][i] = value

problem is, node[keys] returns a node, so the [i] indexing tries to get at another node. basically what I want to be able to do is overload "[ ][ ]" as an operator, which I can't.

is there any way to get at what I'm trying to do?

+14  A: 

Note: This answer talks about implementing something like obj[a][b][c]... that could work with variable number of brackets. It seems it's not exactly what the OP wanted.

You can't overload that directly. You should return an object with an indexer from the first indexer so that you could simulate this functionality.
It's a bit harder to simulate set but it's possible to do something like:

public class Node<T> {
    public Node<T> this[string key] {
        get { return GetChildNode(key); }
        set {
            if (value is DummyNode<T>) {
                GetChildNode(key).Value = value.Value;
            } else {
                // do something, ignore, throw exception, depending on the problem
            }
        }
    } 
    public static implicit operator T(Node<T> value) {
        return value.Value;
    }
    private class DummyNode<T> : Node<T> {
    }
    public static implicit operator Node<T>(T value) {
        return new DummyNode<T> { Value = value };
    }
    public T Value { get; set; }
}
Mehrdad Afshari
In fact, there is no [][] operator. It always just applies [] the the next object, as with jagged arrays.
Lucero
In fact, technically, in C#, [] is not an "operator" at all.
Mehrdad Afshari
Seems like my answer is completely irrelevant to the question :) I thought the question wants to change [x,y,z] to [x][y][z]. I'll leave it here though, if someone needs to do that kind of thing.
Mehrdad Afshari
In fact, technically, in C#, [] _is_ an operator. Why would you suppose that it is not? (It is not classified as an _overloadable_ operator but it is classified as an operator.)
Eric Lippert
@Eric Lippert: Thanks for the correction. Indeed, "overloadable operator" is what I should have said in the above sentence (the term used in the spec). To clarify what I meant: I was trying to say you can't overload it as you would in C++ and declaring an indexer does not count as overloading [].
Mehrdad Afshari
+4  A: 

seems I just needed to tinker a bit more to figure it out...I created a second overload:

public object this[int index]
{
    set { ... }
}

which now lets me do

node["child1", "child1's child1"][i] = value

:)

toasteroven
A: 
var pat = new Tree<string[]>();
pat["test", "test2", "test3"] = new[] { "test3" };
Console.WriteLine(pat["test", "test2", "test3"][0]);

Magic classes are fun...

public class Tree<T>
{
    private Dictionary<string, T> _store = new Dictionary<string, T>();

    private string GetKey(string[] index)
    {
        if (index == null || index.Length == 0) return string.Empty;
        return string.Join(".", index);
    }

    public T this[params string[] index]
    {
        get
        {
            var key = GetKey(index);
            if (!_store.ContainsKey(key))
                return default(T);
            return _store[key];
        }
        set
        {
            var key = GetKey(index);
            if (_store.ContainsKey(key))
                _store.Remove(key);
            if (value != null)
                _store.Add(key, value);
        }
    }
}
Matthew Whited