views:

266

answers:

5

I have an array which really is a function, however i would like to use it as an array. I know i can write these

int var { get{return v2;} }
public int this[int v] { get { return realArray[v]; }

but how do i implement a function that like an array? i would like to do something like

public int pal[int i] { get { return i*2; } }

But that get a compile error

error CS0650: Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.
error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression)
+10  A: 

In C#, the only possible way to declare a parameterized property is an indexer. However, you could simulate something like that by creating a class that provides an indexer and adding a property of that type to your class:

class ParameterizedProperty<TProperty, TIndex> {
     private Func<TIndex, TProperty> getter;
     private Action<TIndex, TProperty> setter;
     public ParameterizedProperty(Func<TIndex, TProperty> getter,
                                  Action<TIndex, TProperty> setter) {
        this.getter = getter;
        this.setter = setter;
     }
     public TProperty this[TIndex index] {
        get { return getter(index); }
        set { setter(index, value); }
     }   
}

class MyType {
    public MyType() {
        Prop = new ParameterizedProperty<string, int>(getProp, setProp);
    }
    public ParameterizedProperty<string, int> Prop { get; private set; }
    private string getProp(int index) {
        // return the stuff
    }
    private void setProp(int index, string value) {
        // set the stuff
    }
}

MyType test = new MyType();
test.Prop[0] = "Hello";
string x = test.Prop[0];

You can extend the idea to read only and write only properties by removing getter or setter from the class as appropriate.

Mehrdad Afshari
code example?..
Robert Harvey
+1  A: 

As you noticed, you cannot name an indexer like that, so either:

public int this[int i] { get { return i * 2; } }

Or alternatively if you are really set on naming it pal:

public class Wrapper
{
    public int this[int i] { get { return i * 2; } }
}

...

public Wrapper pal { get { return _someWrapperInstance; } }

Which can then be accessed pal[ix], pal[3], etc.

jerryjvl
+1  A: 

Either you return an array object:

public int[] pal { get { return realArray; } }

or you return an object that has an indexer:

public class ActingAsArray {
   private int[] _arr;
   public ActingAsArray(int[] arr) { _arr = arr; }
   public int this[int v] { get { return _arr[v]; } }
}

public ActingAsArray pal { get { return new ActingAsArray(realArray); } }
Guffa
+1  A: 

You cannot overload (overloadable operators) the bracket operator in C#. The best you can do is implement an indexer, as you have shown. As per the documentation, you must use the this keyword to implement an indexer. Indexers work much like properties, they have a getter and a setter and you can perform just about any function in the getter or setter.

heavyd
A: 

If you don't mind using a bit of VB.Net, it supports parameterized properties (still beats me why it's not possible in C#, as .Net is obviously capable of doing it)

This way you could create your class in VB.Net and just reference the VB.Net DLL in your project.

This could of course get somewhat annoying if your class changes often :-/

Steffen