2016-06-29 18 views
6

Załóżmy, że zdefiniowałem klasę MyDisposable : IDisposable. Wiem, że mogę dostarczyć zakodowane listy IDisposable obiektów do rachunku using:Czy istnieje sposób na użycie instrukcji z dynamicznie tworzonymi celami?

using (MyDisposable firstDisposable = new MyDisposable(), 
    secondDisposable = new MyDisposable()) 
{ 
    // do something 
} 

Teraz powiedzmy Mam kilka metod, które wykonują operacje na zbiorze moich jednorazowych przedmiotów i chcę to zrobić wewnątrz instrukcji using. To może wyglądać tak (ale to nie działa oczywiście dlatego, że za pomocą bloku spodziewa się jeden lub więcej IDisposable obiektów i olewam pojedynczy obiekt kolekcji):

using (var myDisposables = GetMyDisposables()) 
{ 
    foreach (var myDisposable in myDisposables) 
    { 
     DoSomething(myDisposable); 
     DoSomethingElse(myDisposable); 
    } 
} 

Oto inne metody tylko dla jasności :

static List<MyDisposable> GetMyDisposables() 
{ 
    throw new NotImplementedException(); // return a list of MyDisposable objects 
} 

static void DoSomething(MyDisposable withMyDisposable) 
{ 
    // something 
} 

static void DoSomethingElse(MyDisposable withMyDisposable) 
{ 
    // something else 
} 

Czy jest jakiś sposób, mogę to zrobić z oświadczeniem using? Czy muszę po prostu wyrzucić oświadczenie i ręcznie zutylizować?

+6

Można utworzyć 'DisposableCollection : IDisposable, IEnumerable gdzie T: IDisposable' – Lee

+0

Możesz napisać 'IDisposable', który przechwytuje kolekcję twoich obiektów' MyDisposable' i zrzuca wszystkie jej elementy kiedy pozbądź się go. –

+0

Dlaczego nie dodasz instrukcji using w bloku foreach? – peinearydevelopment

Odpowiedz

7

Jedno podejście, które można wziąć to, aby zbiór IDisposable obiektów, co jest również IDisposable:

class CollectionOfDisposable<T> : IDisposable where T : IDisposable { 
    public IList<T> Members {get; private set;} 
    public CollectionOfDisposable(IEnumerable<T> members) { 
     Members = members.ToList(); 
    } 
    public void Dispose() { 
     var exceptions = new List<Exception>(); 
     foreach (var item in Members) { 
      try { 
       item.Dispose(); 
      } catch (Exception e) { 
       exceptions.Add(e); 
      } 
     } 
     if (exceptions.Count != 0) { 
      throw new AggregateException(exceptions); 
     } 
    } 
} 

Teraz można napisać tak:

using (var myDisposables = GetMyDisposables()) { 
    foreach (var myDisposable in myDisposables.Members) { 
     DoSomething(myDisposable); 
     DoSomethingElse(myDisposable); 
    } 
} 

static CollectionOfDisposable<MyDisposable> GetMyDisposables() { 
    throw new NotImplementedException(); // return a list of MyDisposable objects 
} 
+0

Czy wszyscy możemy się zgodzić, że ta klasa powinna istnieć w FCL? Nie mogę znaleźć czegoś takiego. Właściwie znalazłem to ['System.Reactive.Disposables.CompositeDisposable'] (https://msdn.microsoft.com/en-us/library/system.reactive.disposables.compositedisposable (v = vs.103). aspx), ale wymaga tych [rozszerzeń reaktywnych] (https://msdn.microsoft.com/en-us/library/hh242985 (v = vs.103) .aspx). –

3

Musisz utworzyć własny typ, który implementuje IDisposable i akceptuje kolekcję obiektów jednorazowego użytku w swoim konstruktorze, trzymając je i usuwając je wszystkie, gdy zostanie zutylizowany.

Powiązane problemy