views:

64

answers:

2

I would like to build a generic class that I can use to implement Parameterized Properties in C#. The basic code I want is this:

public class ParameterizedProperty<typeReturn, typeIndexer> {
    private typeReturn oReturn = default(typeReturn);

    public typeReturn this[typeIndexer oIndexer] {
        get { return oReturn[oIndexer]; }
        set { oReturn[oIndexer] = value; }
    }
}

But since typeReturn is unknown/unrestricted the compiler is plotzing on the oReturn[oIndexer] lines.

So how do I get this to work? My first (well, second) thought is to use Reflection in order to conditionally find the indexer (and raise an error if one is not found) or maybe use the where typeReturn: I??? modifier on the class definition. But if I use the modifier, what would I??? be?

Thanks for any solutions to this problem!

NOTE: How to find the Indexer correctly via Reflection is (supposedly) found here: http://www.dotnet247.com/247reference/msgs/3/16665.aspx (see last message).

EDIT: As Matthew pointed out below... I've got something of a typo/bug in the original description... My own fault, really... originally writing this just before bed! The code I want would look more like this:

public class ParameterizedProperty<typeReturn, typeIndexer> {
    private typeReturn[] oReturn;

    public ParameterizedProperty(typeReturn[] oSource) {
        oReturn = oSource;
    }

    public typeReturn this[typeIndexer oIndexer] {
        get { return oReturn[oIndexer]; }
        set { oReturn[oIndexer] = value; }
    }
}

...and what'll you'll bet that works!?

Er, not quite! Still complaining about typeIndexer (wanting an "int-able" type), but much more betterer! I also added in a constructor to solve that pesky "I can't actually set oReturn to anything" problem =)

But even this doesn't look quite right (Arrays are always indexed by INTs, right? if so there's no need for typeIndexer)... I'll have to look at it again at wurk tomorrow =)

+2  A: 

You want something along these lines:

public class ParameterizedProperty<typeReturn, typeIndexer> {
    private Dictionary<typeIndexer, typeReturn> oReturn = new Dictionary<typeIndexer, typeReturn>();

    public typeReturn this[typeIndexer oIndexer] {
        get { return oReturn[oIndexer]; }
        set { oReturn[oIndexer] = value; }
    }
}
s1mm0t
This would indeed work for my purposes, but it seems a bit heavy-weight using a Dictionary to accomplish what a string[] or bool[] would do (never mind that pesky indexer issue ;)I guess a Dictionary approach will get my vote... but for a few days at least I'm gonna hold out/experiment =)
Campbeln
A: 

Since you're evidently not concerned about attaching specific business logic to the getter or setter for this indexed property (like you could do with the default indexer in C# or any property in VB.NET), you need an internal storage mechanism in order to accomplish this.

public class ParameterizedProperty<TReturn, TIndexer>
{
    private Dictionary<TIndexer, TReturn> storage = new Dictionary<TIndexer, TReturn>();

    public TReturn this[TIndexer index]
    {
        get
        {
            TReturn output;

            storage.TryGetValue(index, out output);

            return output;
        }
        set { storage[index] = value; }
    }
}

But all this really does is provide you with a construct similar to a Dictionary but doesn't throw an exception when an index isn't present.

Adam Robinson
I like the use of the TryGetValue (I'll need to look it up, but I'd guess "default(TReturn)" is placed in output if the get fails?).And yes... no need to attach add'l functionality to these indexers/properties (could always overload/implement a hook I suppose), I just want...public string[] IDs { get { return ga_sIDs; }}...without exposing ga_sIDs to the caller (nor all it's properties/methods).
Campbeln
@CampbeIn: Yes, `default(TReturn)` is what's put into the `out` variable if the retrieval fails.
Adam Robinson
@CampbeIn: Additionally, a `Dictionary` is the only way to get what you're looking for if you want an arbitrary indexing scheme. An array won't work. The `Dictionary` is not a particularly heavyweight object.
Adam Robinson