Свойства, отображающие элементы массива в С#

Я хочу создать свойство в С#, которое устанавливает или возвращает отдельный элемент массива. В настоящее время у меня есть это:

private string[] myProperty;
public string MyProperty[int idx]
{
    get
    {
        if (myProperty == null)
            myProperty = new String[2];

        return myProperty[idx];
    }
    set
    {
        myProperty[idx] = value;
    }
}

Однако я получаю следующую ошибку компиляции:

Неверный идентификатор массива: для объявления управляемого массива спецификатор рангов предшествует идентификатору переменной. Чтобы объявить поле буфера фиксированного размера, используйте ключевое слово fixed до типа поля.

Ответ 1

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

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

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

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<T>.

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

        set
        {
            myProp = value;
        }
    }

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

Ответ 5

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

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

Ответ 6

Опция состоит в том, чтобы перекодировать ее следующим образом:

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

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

Ответ 7

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

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];
    }
}

Ответ 8

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

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
    }
}

Ответ 9

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

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

Ответ 10

Вам нужно использовать индекс. Он работает по-другому. Пример:

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...