Свойства, выставляющие элементы массива в C # - PullRequest
12 голосов
/ 23 августа 2010

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

Ответы [ 10 ]

14 голосов
/ 23 августа 2010

Как насчет этого: написать класс, который выполняет одно и только одно: обеспечивает произвольный доступ к элементам некоторой базовой индексированной коллекции. Дайте этому классу 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>.

5 голосов
/ 23 августа 2010

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

5 голосов
/ 23 августа 2010

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

2 голосов
/ 23 августа 2010

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

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 голосов
/ 23 августа 2010

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

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

        set
        {
            myProp = value;
        }
    }

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

1 голос
/ 23 августа 2010

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

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

1 голос
/ 23 августа 2010

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

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 голос
/ 23 августа 2010

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

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 голос
/ 23 августа 2010

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

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

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

0 голосов
/ 23 августа 2010

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

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...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...