Свойства, представляющие элементы массива в C #

Я хочу создать свойство в 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 перед типом поля.

13
задан abatishchev 23 August 2010 в 13:13
поделиться

10 ответов

Как насчет этого: напишите класс, который делает одну и только одну вещь: обеспечивает случайный доступ к элементам некоторой базовой индексированной коллекции. Дайте этому классу этот индексатор.

Для свойств, к которым вы хотите обеспечить произвольный доступ, просто верните экземпляр этого класса индексатора.

Тривиальная реализация:

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.

14
ответ дан 1 December 2019 в 19:58
поделиться

C # допускает только одно индексируемое свойство для каждого класса, поэтому вы вынуждены использовать это.

5
ответ дан 1 December 2019 в 19:58
поделиться

Вы должны использовать this в качестве имени свойства для индексаторов.

5
ответ дан 1 December 2019 в 19:58
поделиться

Можно перекодировать его следующим образом:

private string[] myProperty = new string[2]; 
public string[] MyProperty
{ 
    get 
    { 
        return myProperty;
    } 
    set 
    { 
        myProperty = value; 
    } 
} 

Он скомпилируется, но у него есть свой набор проблем (fxCop будет кричать об этом, но он может навести вас на другие варианты).

1
ответ дан 1 December 2019 в 19:58
поделиться

Во-первых, объявление в поле позволяет избежать лишних проверок:

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
    }
}
1
ответ дан 1 December 2019 в 19:58
поделиться

C# не предоставляет встроенного механизма для создания индексированных свойств. Вы можете использовать индексатор на уровне класса (используя this[int index] нотацию), но ничего подобного на уровне свойства.

Один из вариантов - создать вспомогательный класс с индексатором и использовать этот класс в качестве типа свойства. Смотрите пример на MSDN.

1
ответ дан 1 December 2019 в 19:58
поделиться

Вам необходимо использовать индексатор. Это работает немного иначе. См. Пример:

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...
0
ответ дан 1 December 2019 в 19:58
поделиться

Вы можете использовать его следующим образом:

    private string[] myProp;
    public string[] MyProp
    {
        get
        {
            if (myProp == null)
            {
                myProp = new String[2];
            }
            return myProp;
        }

        set
        {
            myProp = value;
        }
    }

И возможно получить доступ к myProp [1] как MyProp [1], например,

2
ответ дан 1 December 2019 в 19:58
поделиться

Отображение вашего массива через свойство только для чтения может покрыть твои нужды. Поскольку вы не хотите, чтобы другой код назначал массив как таковой, нет необходимости в общедоступном сеттере:

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
2
ответ дан 1 December 2019 в 19:58
поделиться

Вы можете сделать что-то вроде этого:

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];
    }
}
1
ответ дан 1 December 2019 в 19:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: