Вернуть ReadOnlyCollection из IList <> - PullRequest
12 голосов
/ 29 августа 2011

ОК, поэтому List <> содержит AsReadOnly (), который предоставляет вам коллекцию ReadOnlyCollection.Мне нужно иметь поле типа IList и свойство, которое будет возвращать коллекцию ReadOnlyCollection для этого списка.

Пример класса:

class Test
{
   private IList<Abc> list;

   public AddToList(Abc someItem) { /* adds inside the list */... }

   public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}

Сценарий следующий: мне нужно иметь некоторую настраиваемую логику внутри моего класса, когда элемент добавляется в список, и я хочу ограничить добавление в негосписок, вызывая AddToList (someitem), но не позволяя использовать list.Add (someItem).Проблема в том, что я использую NHibernate , для которого требуется интерфейс IList , поэтому я не могу привести / вызвать AsReadOnly () для IList (он не содержит этот метод).

Как бы вы порекомендовали решить эту ситуацию?Мне просто нужно, чтобы NHibernate каким-то образом установил нужную коллекцию, но мне также нужно ограничить пользователей.

Ответы [ 5 ]

26 голосов
/ 29 августа 2011

Вы можете просто эмулировать AsReadOnly():

public ReadOnlyCollection<Abc> List
{
    get { return new ReadOnlyCollection<Abc>(list); }
}

UPDATE :
Это не создает копию list.ReadOnlyCollection не копирует данные, он работает непосредственно с предоставленным списком.См. документацию :

Коллекция, доступная только для чтения, - это просто коллекция с оболочкой, которая предотвращает изменение коллекции;поэтому, если в базовую коллекцию вносятся изменения, коллекция только для чтения отражает эти изменения.
Этот конструктор является операцией O (1).

6 голосов
/ 29 августа 2011

1001 * попробовать *

return new ReadOnlyCollection<Abc> (list);
2 голосов
/ 29 августа 2011

На мой взгляд, лучший способ сделать это - вернуть IEnumerable<Abc>, используя метод , предложенный Джоном Скитом :

public IEnumerable<Abc> Abcs {
    get { return list.Skip(0); }
}

Если вы не беспокоитесь о кастинге потребителейIEnumerable<T> обратно к IList<T> вы можете просто вернуть IEnumerable<T>.

ReadOnlyCollection<T> имеет некоторые серьезные недостатки, основным из которых является то, что он реализует IList<T>, поэтому у него есть методы Add и Remove.Это может привести к ошибкам во время выполнения, если потребители не будут проверять его свойство ReadOnly.Я настоятельно рекомендую не использовать его.

1 голос
/ 29 августа 2011

Вы также можете вернуть IEnumerable<Abc>, который предназначен только для чтения, и предоставить методы для добавления и удаления элементов.

1 голос
/ 29 августа 2011

Использовать следующим образом,

public class Test
    {

        private IList<SubTest>      _subTests;


        public virtual void AddSubTest(SubTest SubTest)
        {
            if (_subTests == null)
                _subTests = new List<SubTest>();

            _subTests.Add(SubTest);

            return this;
        }


        public virtual IReadOnlyList<SubTest> SubTests
        {
            get
            {
                if (_subTests == null)
                    _subTests = new List<SubTest>();

                return _subTests.AsReadOnly();
            }
        }




        public void RemoveSubTest( SubTest SubTest )
        {
            if( _subTests == null ) 
                return;

            _subTests.Remove( SubTest );            
        }

    }

использовать следующее отображение, и оно установит значение в поле, а не в свойство, доступное только для чтения в списке

<bag 
      name="SubTests" table="SubTest" lazy="true" access="field.camelcase-underscore"
      optimistic-lock="false"
      >
      <key column ="TestID" />
      <many-to-many class="SubTest, Domain" column="SubTestID" />
    </bag>
...