C #, свойство ArrayList в поле списка - PullRequest
0 голосов
/ 22 августа 2010

У меня есть следующее поле:

private IList<Modulo> modulos;

и следующее свойство:

    public virtual ArrayList XmlModulos
    {
        get
        {
            if (modulos == null) return new ArrayList();
            var aux = new ArrayList();
            foreach (Modulo m in modulos)
                aux.Add(m);
            return aux;
        }
        set
        {
            modulos = new List<Modulo>();
            foreach (object o in value)
                modulos.Add((Modulo)o);
        }

    }

Функция get работает отлично, поскольку у меня есть другое прямое свойство, которое используется для различных целей.Но набор не работает, так как когда я использую это свойство, он ничего не обновляет.Отладка говорит, что Property является пустым ArrayList (count 0) и поле остается пустым.Любая идея, почему это не работает?любая помощь будет высоко оценена.

Ответы [ 2 ]

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

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

То есть они в основном отображают эти операции:

ArrayList m = obj.XmlModulos;

obj.XmlModulos = new ArrayList();

к коду, который действительно более похож на это:

ArrayList m = obj.get_XmlModulos();

obj.set_XmlModulos(new ArrayList());

ОК, так что с учетом этого давайте рассмотрим, что вы пытаетесь сделать (это основано на комментарии к ответу Тимви ):

obj.XmlModulos.Add(new Modulo());

Что на самом деле 1017 * делает:

obj.get_XmlModulos().Add(new Modulo());

Учитывая, что ваш get аксессор создает новый ArrayList, вы никогда не сможете добавить Modulo в свою коллекцию таким образом. Единственный способ сделать это - это

ArrayList m = obj.XmlModulos;

m.Add(new Modulo());

obj.XmlModulos = m;

ОДНАКО , это очень неэффективный способ реализации ваших get и set аксессоров . Создание нового ArrayList для каждого get и заполнение его текущими членами modulos является дорогостоящим. Так же перечисляются все значения, переданные в set, и копируются каждое в modulos.

Во всяком случае, дизайн этого класса задом наперед (на самом деле, большинство разработчиков в наши дни советуют полностью исключить тип ArrayList, но если вы настаиваете, это ваш вызов). Вы храните IList<Modulo> (который обеспечивает безопасность типов) внутри, но выставляете ArrayList (который делает не ) внешне; это означает, что кто-то может легко попытаться добавить какой-либо случайный объект не Modulo типа в ваш список, и вы получите InvalidCastException. Код, который пытается это сделать, вообще не должен компилироваться; в этом весь смысл дженериков.

Хорошо, я сказал достаточно. Что я предлагаю? Имейте только одну коллекцию, принадлежащую этому классу. Решите, какую функциональность вы на самом деле хотите предоставить, и представьте только эту функциональность. Не делайте этого дорогого копирования между двумя коллекциями.

Например, если вам действительно нужен ArrayList, но вам нужно только разрешить клиентскому коду добавлять и удалять элементы в него и из него, то реализуйте его следующим образом:

private ArrayList modulos;

public void AddModulo(Modulo m)
{
    modulos.Add(m);
}

public bool RemoveModulo(Modulo m)
{
    return modulos.Remove(m);
}

Таким образом, даже если вы используете неуниверсальный ArrayList для внутреннего использования (если для этого есть веские причины), вы все равно получаете эффективную безопасность типов IList<T>, только позволяя клиентскому коду добавлять и удалять элементы типа Modulo.

Это может сильно отличаться от решения, которое действительно имеет для вас смысл. Пусть он, надеюсь, направит вас в правильном направлении, по крайней мере.

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

Я не могу воспроизвести вашу проблему;Я скопировал ваш код и затем выполнил следующую строку:

XmlModulos = new ArrayList { new Modulo() };

После этого и отладчик, и Console.WriteLine сообщают и modulos.Count, и XmlModulos.Count как 1.

Поэтомуошибка кроется в каком-то другом коде, который вы нам не показали.

...