Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to have a using statement with dynamically-created targets?

Let's say I've defined a class MyDisposable : IDisposable. I know I can provide a hard-coded list of IDisposable objects to the using statement:

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

Now let's say I have a few methods that perform operations on a collection of my disposable objects, and I want to do this inside a using statement. It might look like this (but this doesn't work of course because the using block expects one or more IDisposable objects and I'm passing a single collection object):

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

Here are the other methods just for clarity:

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
}

Is there some way I can accomplish this with the using statement? Or do I do just have to throw out the statement and manually dispose?

like image 791
rory.ap Avatar asked Jun 29 '16 13:06

rory.ap


People also ask

How to dynamically create objects in c#?

You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.

Is it good to use dynamic type in C#?

It is definitely a bad idea to use dynamic in all cases where it can be used. This is because your programs will lose the benefits of compile-time checking and they will also be much slower.

What is dynamic keyword in C#?

The dynamic keyword is new to C# 4.0, and is used to tell the compiler that a variable's type can change or that it is not known until runtime. Think of it as being able to interact with an Object without having to cast it. dynamic cust = GetCustomer(); cust.


2 Answers

One approach that you can take is to make a collection of IDisposable objects, which is also 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);
        }
    }
}

Now you can write this:

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
}
like image 98
Sergey Kalinichenko Avatar answered Oct 07 '22 00:10

Sergey Kalinichenko


You'll have to create your own type that implements IDisposable and accepts a collection of disposable objects in its constructor, holding onto them and disposing of them all when it is disposed.

like image 35
Servy Avatar answered Oct 06 '22 23:10

Servy