Нужно ли иметь методы, которые возвращают списки одноразовых экземпляров? - PullRequest
6 голосов
/ 29 января 2010

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

Должен ли я вернуть IList<MyClass> из моих методов или я должен создать класс MyClassCollection, который также является одноразовым, и вернуть его вместо этого?

EDIT:

Моя главная причина, по которой я спрашиваю, состоит в том, что я довольно часто этим занимаюсь:

IList<MyObject> list = GetList();
foreach(MyObject obj in list)
{
     //do something
     obj.Dispose();
} 

и мне кажется, что лучше было бы:

using (IList<MyObject> list = GetList())
{
     foreach(MyObject obj in list)
     {
     //do something

     } 
}

Ответы [ 5 ]

3 голосов
/ 29 января 2010

Может быть проще сгенерировать последовательность элементов (IEnumerable<T>), а не список - есть способы сделать время жизни каждого из них связанным с итератором, так что:

  • у вас есть только один за раз (я полагаю, они дорогие)
  • они избавляются, когда их время истекло
  • они все расположены, даже по ошибке

Это тема, которую я изучил здесь с использованием LINQ, но есть и другие способы, если ваш источник является (или может быть) последовательностью.

2 голосов
/ 29 января 2010

Полностью клиентский код должен вызывать ваш метод Dispose (). Только он знает, когда это делается с помощью объектов. Вы никак не можете помочь, потому что не знаете, как будет выглядеть этот код. Создание объектов списка, которые располагают свои элементы, не очень хорошая идея. Каркас не содержит объекта коллекции, который делает это. Вы просто запутаете программиста клиентского кода.

2 голосов
/ 29 января 2010

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

Возможно, вы могли бы сделать обобщенный IDisposableList<T> с ограничением на T where T : IDisposable и сделать так, чтобы ваш класс реализовал IDisposable, вызвав Dispose для всех его элементов? Затем вы можете повторно использовать этот класс для всех ваших IDisposable типов.

1 голос
/ 29 января 2010

Вы также можете использовать расширение, если хотите:

static class Extensions
{
 public static void DoStuffAndDisposeElements<T> ( this List<T> list, Action<T> action )
 {
        list.ForEach ( x => { action ( x );
               IDisposable disposable = (x as IDisposable);
               if ( disposable != null )
                  disposable.Dispose ();

        } );
 }


}

по которому можно позвонить:

getList().DoStuffAndDisposeElements ( x => doStuff(x));

Не уверен, сколько вы выиграете от этого, но могут быть ситуации, когда это будет полезно;)

1 голос
/ 29 января 2010

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

public class ListScope : IDisposable
{
    private IList list;
    public ListScope(IList list)
    {
        this.list = list;
    }

    #region IDisposable Members

    public void Dispose ()
    {
        foreach ( object o in this.list )
        {
            IDisposable disposable = ( o as IDisposable );
            if (disposable != null)
                    disposable.Dispose ();
        }
    }

    #endregion
}

Вы можете использовать как:

using ( new ListScope ( list ) )
{
   // Do stuff with list
}
...