Re: Is it possible to have parameters in a property?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Stu wrote:
I have a private array in a class, and I was just wondering if it's
possible to expose its elements with "array-like" syntax through a
property without exposing the full array, instead of using a method.
So for instance could I do something like this:

public class MyClass
{
private int[] _NumberArray = new int[100];
public int NumberArray[int index]
{
get
{
return _NumberArray[index];
}
set
{
_NumberArray[index] = value;
}
}

public MyClass(){}
}

Then call it like this so that when MyClass.NumberArray[index] gets
assigned a value, it does it through the property:
MyClass myClass = new MyClass();
myClass.NumberArray[index] = 5;

I know this is easily accomplished through a method, but then I have
to pass the index and value as parameters rather than using array-like
syntax. Not a big deal, more a matter of curiosity.

In C#, no. VB.NET has indexed properties, which are similar to a class indexer in C#, except you can give it a property name. But in C#, the only indexer you can declare is for the class itself.

In C#, the proper idiom is to define a property that itself is a type with an indexer. That's assuming it makes sense to provide access to the array in this way at all, which is not always true (people often want to construct their class in counter-intuitive ways :) ).

What approach is appropriate depends on the relationship between the array and the class containing it. If the array is just an implementation detail of a class that is itself array-like, then simply giving the class an indexer is probably best:

public class MyClass
{
private int[] _NumberArray = new int[100];
public int this[int index]
{
get
{
return _NumberArray[index];
}
set
{
_NumberArray[index] = value;
}
}

public MyClass(){}
}

Usage example:

MyClass obj = new MyClass();

obj[50] = 17;
Console.WriteLine(obj[25]);

On the other hand, often an array in a class is a contained object that the class is responsible for maintaining. In those cases, either you want to prevent modifications to the array or you don't (and if you're providing a "set" method in an indexed property, obviously you don't want to prevent modifications to the array).

If you don't want to prevent modifications to the array, then just define a property that returns the array object. Code can then index off of _that_ property. It will look just like an indexed property, but will be using the "approved" C# mechanism of a plain named property along with a returned class with its own indexer:

public class MyClass
{
private int[] _NumberArray = new int[100];
public int[] NumberArray
{
get
{
return _NumberArray;
}
}

public MyClass(){}
}

Usage example:

MyClass obj = new MyClass();

obj.NumberArray[50] = 17;
Console.WriteLine(obj.NumberArray[25]);

In other cases, it can be useful to do basically the above, but return something other than the actual object type declared. In some cases, that's just a matter of using an interface the object already implements (e.g. ICollection), while in other cases it's a matter of wrapping the object in something that provides greater control (e.g. preventing modification of the object, by returning Array.AsReadOnly())

Finally, note that you can provide arbitrarily complex degree of control over access by defining your own wrapper type that would be exposed by a named property, and putting that control in that type.

For example:

public class MyClass
{
private int[] _NumberArray = new int[100];

public class Indexer
{
private MyClass _obj;

public Indexer(MyClass obj)
{
_obj = obj;
}

public int this[int i]
{
get { return _obj._NumberArray[i]; }
set { _obj._NumberArray[i] = value; }
}
}

public Indexer NumberArray
{
get
{
return new Indexer(this);
}
}

public MyClass(){}
}

Usage example:

MyClass obj = new MyClass();

obj.NumberArray[50] = 17;
Console.WriteLine(obj.NumberArray[25]);

Obviously in a real-world example, you'd put whatever specific access controls you want into the "Indexer" class. You can enhance encapsulation by exposing only an interface, and keeping the implementation private:

public class MyClass
{
private int[] _NumberArray = new int[100];

public interface IIndexer
{
public int this[int i] { get; set; }
}

private class Indexer : IIndexer
{
private MyClass _obj;

public Indexer(MyClass obj)
{
_obj = obj;
}

public int this[int i]
{
get { return _obj._NumberArray[i]; }
set { _obj._NumberArray[i] = value; }
}
}

public IIndexer NumberArray
{
get
{
return new Indexer(this);
}
}

public MyClass(){}
}

Usage example:

MyClass obj = new MyClass();

obj.NumberArray[50] = 17;
Console.WriteLine(obj.NumberArray[25]);

(Warning: all of the above code is uncompiled, untested, example code only).

Anyway, hopefully that gives you some ideas as to the best way to expose your indexed data, whatever the exact context turns out to be.

Pete
.



Relevant Pages

  • Re: how to write array elements to console
    ... private void f{ ... Downcasting works if the Object happens to be an array at runtime for the downcast. ... public void foo(Object obj) ...
    (comp.lang.java.programmer)
  • Re: Concept of Indexer
    ... A good example of a class using an indexer is ArrayList. ... //note we access it like an array even though it is not ... what you have in fact created is an array of ArrayLists, ... And as such the array, lists[], will initialy contain nothing but null ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: JSON array, cant access result ?!?!
    ... correct technique for looping through an array anyway. ... the first seems to be from "for (var i in obj)", ... global scope completion routine was written because ...
    (comp.lang.javascript)
  • Re: Using property to access elements of array?
    ... Actually, you do want an indexer, but not on the class that exposes the ... array elements through an indexer, then expose an instance of that class ... > activate something whenever the set method is invoked. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: JSON array, cant access result ?!?!
    ... verify that the object was populated, and that the array is present. ... DEBUG: ... the first seems to be from "for (var i in obj)", ...
    (comp.lang.javascript)