A.Pissicat
A.Pissicat

Reputation: 3265

Get/Set for element of array property

I have a class used to define/save a rectangle.

I have 2 array containing 4 Points. One array is for points saved in file, the other one is for points actually display (can be modify by user).

I want to create a get/set for elements in array with saved points. When I save a point, it is automatically copied in second array.

I not sure to be very clear, there is the code I want to create :

public class MyRectangle
{
    public PointF[] TemporaryPoints = new PointF[4];

    protected PointF[] _savedPoints = new PointF[4];
    protected PointF[] SavedPoints;

    //How to do something like this ?
    protected PointF SavedPoints[int i]
    {
        get
        {
            return _savedPoints[i];
        }
        set
        {
            _savedPoints[i] = value;
            TemporaryPoints[i] = value;
        }
    }
}

Used like this :

SavedPoints[0] = new PointF(1,1);     // SavedPoints = [1;1] TemporaryPoints = [1;1]
TemporaryPoints[0] = new PointF(4,4); // SavedPoints = [1;1] TemporaryPoints = [4;4]
SavedPoints[0] = TemporaryPoints[0];  // SavedPoints = [4;4] TemporaryPoints = [4;4]

Upvotes: 0

Views: 114

Answers (3)

Sefe
Sefe

Reputation: 14007

Named indexers are not possible in C#. You can use indexer syntax:

public class MyRectangle
{
    public PointF[] TemporaryPoints = new PointF[4];

    protected PointF[] _savedPoints = new PointF[4];

    protected PointF this[int i]
    {
        get
        {
            return _savedPoints[i];
        }
        set
        {
            _savedPoints[i] = value;
            TemporaryPoints[i] = value;
        }
    }
}

That doesn't give you an option to access an indexed property with the name SavedPoints. If you want to do that you have to create a custom collection SavedPointsCollection that encapsulates this functionality. You can then define a SavedPoints property of that type. If necessary, you also can create a TemporaryPintsCollection that is accessed by SavedPointsCollection.

To implement a custom collection you can either override System.Collections.ObjectModel.Collection<T> or implement the IList<T> interface. Collection<T> is good when you want to use a standard collection for an item type. When you want to do more fancy features, suche as a fixed-size collection, you can use IList<T>.

Here's an example with an (incomplete) IList<T> implementation:

public class SavedPointsCollection : IList<PointF> {
    protected PointF[] _values = new PointF[4];

    public PointF this[int index] {
        get
        {
            return _values[index];
        }
        set
        {
            _values[index] = value;
            //Set temporary points here
        }
    }

    //Rest of the IList implementation
}


public class MyRectangle
{
    private SavedPointsCollection _savedPoints = new SavedPointsCollection();

    protected SavedPointsCollection SavedPoints
    {
        get {
            return _savedPoints;
        }
    }
}

Upvotes: 1

mrogal.ski
mrogal.ski

Reputation: 5920

If you want to do such thing you can override this[] indexer property but you should create a property TemporaryPoints instead of making it a public field. These you can combine to create something like this:

public class MyRectangle
{
    private PointF[] _temporaryPoints = new PointF[4];
    protected PointF[] _savedPoints = new PointF[4];

    // get TemporaryPoint by it's index
    public PointF TemporaryPoint(int idx)
    {
        return (idx < _temporaryPoints.Length ? _temporaryPoints[idx] : default(PointF));
    }

    // set TemporaryPoint value at index idx
    public void SetTemporaryPoint(int idx, PointF value)
    {
        if(idx < _temporaryPoints.Length) _temporaryPoints[idx] = value;
    }

    // get SavedPoint by it's index
    public PointF SavedPoint(int idx)
    {
        return (idx < _savedPoints.Length ? _savedPoints[idx] : default(PointF));
    }    

    // set SavedPoint value at index idx
    public void SetSavedPoint(int idx, PointF value)
    {
        if(idx < _savedPoints.Length) _savedPoints[idx] = value;
    }

    //How to do something like this ?
    protected PointF this[int idx]
    {
        get
        {
            return SavedPoint(idx);
        }
        set
        {
            SetSavedPoint(i, value);
            SetTemporaryPoint(i,  value);
        }
    }
}

Since you cannot override "property's indexer property" you should make interface which allows you to set only the value on the specific index. That's why there's this method : SetTemporaryPoint(int idx, PointF value). After all you can use it almost the same as you wanted which is :

SetSavedPoint(0, new PointF(1,1));     // SavedPoints = [1;1] TemporaryPoints = [1;1]
SetTemporaryPoint(0, new PointF(4,4)); // SavedPoints = [1;1] TemporaryPoints = [4;4]
SetSavedPoint(0, TemporaryPoint(0));  // SavedPoints = [4;4] TemporaryPoints = [4;4]

But if you're really into using only this[] indexer property. You can make some enumeration :

public enum POINTS_STORAGE { TEMPORARY = 0, SAVED = 1 };

Then in you this[] indexer property :

public PointF this[POINTS_STORAGE s, int idx]
{
    get
    {
        if(s == POINTS_STORAGE.TEMPORARY)
            return _temporaryPoints[idx];
        else
            return _savedPoints[idx];
    }

    set
    {
        if(s == POINTS_STORAGE.TEMPORARY)
            _temporaryPoints[idx] = value;
        else
            _savedPoints[idx] = value;
    }
}

Then you can use it like :

meRectangleReference[POINTS_STORAGE.SAVED, 0] = new PointF(1, 1);     // SavedPoints = [1;1] TemporaryPoints = [1;1]
meRectangleReference[POINTS_STORAGE.TEMPORARY, 0] = new PointF(4,4); // SavedPoints = [1;1] TemporaryPoints = [4;4]
meRectangleReference[POINTS_STORAGE.SAVED, 0] =  meRectangleReference[POINTS_STORAGE.TEMPORARY, 0];  // SavedPoints = [4;4] TemporaryPoints = [4;4]

Upvotes: 0

Tim Rutter
Tim Rutter

Reputation: 4679

Not absolutely clear what you want but you could use an indexer:

protected PointF this[int index]    // Indexer declaration  
{  
     get
    {
        return _savedPoints[index];
    }
    set
    {
        _savedPoints[index] = value;
        TemporaryPoints[index] = value;
    } 
}  

You can then do:

 var rect = new MyRectangle();
rect[0] = new PointF (1,1);

Upvotes: 0

Related Questions