Reputation: 16685
I want to create a property in C# that sets or returns an individual member of an array. Currently, I have this:
private string[] myProperty;
public string MyProperty[int idx]
{
get
{
if (myProperty == null)
myProperty = new String[2];
return myProperty[idx];
}
set
{
myProperty[idx] = value;
}
}
However, I get the following compile error:
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.
Upvotes: 13
Views: 17828
Reputation: 100238
First, in-field declaration avoids excess check:
private string[] myProperty = new string[2];
You can implement several indexers via overloading by input type:
public string this[int index]
{
get
{
return myProperty[index];
}
set
{
myProperty[index] = value;
}
}
public object this[object a, object b] // different input type(s) (and different return type)
{
get
{
// do other stuff
}
}
Upvotes: 1
Reputation: 10349
C# provides no built-in mechanism to create indexed properties. You can use a class-level indexer (using this[int index]
notation), but nothing like this on a property level.
One option is to create a helper class with an indexer and use this class as the property type. See an example on MSDN.
Upvotes: 1
Reputation:
You need to use an indexer. It works a little differently. See example:
public class Node
{
public Node this[int offset]
{
get { return localList[offset]; }
}
}
Note: You are allowed only one indexer per class. The reason is that it is too confusing to the compiler as to the meaning, so you only are allowed one.
You can also do this:
private static int[] _widget = new int[Counter];
public static int [] Widget
{
get { return _widget; }
set { _widget = value; }
}
...
for (int i = 0; i < MyClass.Counter; i++)
{
MyClass.Widget[i] = i;
}
...
double _newWidget5 = MyClass.Widget[5];
// and so on...
Upvotes: 0
Reputation: 158289
Exposing your array through a read-only property might cover your needs. Since you don't want to allow other code to assign the array as such, there is no need for a public setter:
private string[] myProperty;
public string[] MyProperty
{
get
{
if (myProperty == null)
{
myProperty = new String[2];
}
return myProperty;
}
}
Then you can write code as such:
theObject.MyProperty[1] = "some string";
...but you cannot replace the array itself:
theObject.MyProperty = new string[2]; // will not compile
Upvotes: 2
Reputation: 4502
You can use it this way:
private string[] myProp;
public string[] MyProp
{
get
{
if (myProp == null)
{
myProp = new String[2];
}
return myProp;
}
set
{
myProp = value;
}
}
And it's possible to acces myProp[1] as MyProp[1] for Example
Upvotes: 2
Reputation: 13740
You could do something like this:
class Indexers
{
private string[] _strings = new [] {"A","B"};
private int[] _ints = new[] { 1, 2 };
public string[] Strings
{
get{ return _strings;}
}
public int[] Ints
{
get{ return _ints;}
}
}
class Program
{
static void Main(string[] args)
{
Indexers indexers = new Indexers();
int a1 = indexers.Ints[0];
string a2 = indexers.Strings[0];
}
}
Upvotes: 1
Reputation: 128317
How about this: write a class that does one thing and one thing only: provide random access to elements of some underlying indexed collection. Give this class a this
indexer.
For properties that you want to provide random access to, simply return an instance of this indexer class.
Trivial implementation:
public class Indexer<T>
{
private IList<T> _source;
public Indexer(IList<T> source)
{
_source = source;
}
public T this[int index]
{
get { return _source[index]; }
set { _source[index] = value; }
}
}
public static class IndexHelper
{
public static Indexer<T> GetIndexer<T>(this IList<T> indexedCollection)
{
// could cache this result for a performance improvement,
// if appropriate
return new Indexer<T>(indexedCollection);
}
}
Refactoring into your code:
private string[] myProperty;
public Indexer<string> MyProperty
{
get
{
return myProperty.GetIndexer();
}
}
This will allow you to have as many indexed properties as you want, without needing to expose those properties with the IList<T>
interface.
Upvotes: 15
Reputation: 4163
An option is to recode it as follows:
private string[] myProperty = new string[2];
public string[] MyProperty
{
get
{
return myProperty;
}
set
{
myProperty = value;
}
}
It'll compile, but it does have its own set of issues (fxCop will yell about it, but it can lead you to other options).
Upvotes: 1
Reputation: 221
C# allows only one indexed property per class, so you are forced to use this.
Upvotes: 5