Я хочу создать свойство в C #, которое устанавливает или возвращает отдельный член массива. В настоящее время у меня есть это:
private string[] myProperty;
public string MyProperty[int idx]
{
get
{
if (myProperty == null)
myProperty = new String[2];
return myProperty[idx];
}
set
{
myProperty[idx] = value;
}
}
Однако, я получаю следующую ошибку компиляции:
Неверный декларатор массива: Чтобы объявить управляемый массив, спецификатор ранга предшествует идентификатору переменной. Чтобы объявить поле буфера фиксированного размера, используйте ключевое слово fixed перед типом поля.
Как насчет этого: напишите класс, который делает одну и только одну вещь: обеспечивает случайный доступ к элементам некоторой базовой индексированной коллекции. Дайте этому классу этот
индексатор.
Для свойств, к которым вы хотите обеспечить произвольный доступ, просто верните экземпляр этого класса индексатора.
Тривиальная реализация:
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);
}
}
Рефакторинг в ваш код:
private string[] myProperty;
public Indexer<string> MyProperty
{
get
{
return myProperty.GetIndexer();
}
}
Это позволит вам иметь столько индексированных свойств, сколько вы хотите, без необходимости раскрывать эти свойства с помощью интерфейса IList
.
C # допускает только одно индексируемое свойство для каждого класса, поэтому вы вынуждены использовать это.
Вы должны использовать this
в качестве имени свойства для индексаторов.
Можно перекодировать его следующим образом:
private string[] myProperty = new string[2];
public string[] MyProperty
{
get
{
return myProperty;
}
set
{
myProperty = value;
}
}
Он скомпилируется, но у него есть свой набор проблем (fxCop будет кричать об этом, но он может навести вас на другие варианты).
Во-первых, объявление в поле позволяет избежать лишних проверок:
private string[] myProperty = new string[2];
Вы можете реализовать несколько индексаторов путем перегрузки по типу ввода:
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
}
}
C# не предоставляет встроенного механизма для создания индексированных свойств. Вы можете использовать индексатор на уровне класса (используя this[int index]
нотацию), но ничего подобного на уровне свойства.
Один из вариантов - создать вспомогательный класс с индексатором и использовать этот класс в качестве типа свойства. Смотрите пример на MSDN.
Вам необходимо использовать индексатор. Это работает немного иначе. См. Пример:
public class Node
{
public Node this[int offset]
{
get { return localList[offset]; }
}
}
Примечание. Допускается использование только одного индексатора для каждого класса. Причина в том, что это слишком сбивает компилятора с толку, поэтому вам разрешено только одно.
Вы также можете сделать это:
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...
Вы можете использовать его следующим образом:
private string[] myProp;
public string[] MyProp
{
get
{
if (myProp == null)
{
myProp = new String[2];
}
return myProp;
}
set
{
myProp = value;
}
}
И возможно получить доступ к myProp [1] как MyProp [1], например,
Отображение вашего массива через свойство только для чтения может покрыть твои нужды. Поскольку вы не хотите, чтобы другой код назначал массив как таковой, нет необходимости в общедоступном сеттере:
private string[] myProperty;
public string[] MyProperty
{
get
{
if (myProperty == null)
{
myProperty = new String[2];
}
return myProperty;
}
}
Затем вы можете написать код как таковой:
theObject.MyProperty[1] = "some string";
... но вы не можете заменить сам массив :
theObject.MyProperty = new string[2]; // will not compile
Вы можете сделать что-то вроде этого:
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];
}
}