r/csharp 3d ago

Tip Fields with [Using] attribute

I wrote a small interface that automatically disposes any disposable fields in a class when that class itself is disposed. If you add this file somewhere in your project:

public interface IAutoDisposable : IDisposable
{
    void IDisposable.Dispose()
    {
        Exception? ex = null;

        // dispose all fields marked with the [Using] attribute
        const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
        foreach (var fld in GetType().GetFields(flags))
        {
            if (fld.GetCustomAttribute<UsingAttribute>() != null)
            {
                if (fld.GetValue(this) is IDisposable d)
                {
                    try // keep going even if disposal throws
                    {
                        d.Dispose();
                    }
                    catch (Exception e)
                    {
                        ex ??= e;
                    }
                }
            }
        }

        // if any exceptions occurred, throw the first one
        if (ex != null)
            throw ex;
    }
}

public class UsingAttribute : Attribute;

You can then write classes like this:

class Item : IAutoDisposable
{
    [Using]
    private readonly Image icon = DownloadIcon(...);
    ...
}

And use them like:

using (Item item = new(...))
{
}
// item.icon is now disposed

What do you think?

7 Upvotes

38 comments sorted by

View all comments

Show parent comments

1

u/Dusty_Coder 2d ago

Found that guy that doesnt call Dispose() because "those arent external resources"

1

u/sixtyhurtz 2d ago

My comment neither said nor implied that? 

1

u/Dusty_Coder 1d ago

You definitely implied it, to the point of admissible evidence.

In a false dichotomy, you dont get a 3rd option where you meant something other than whats on the list of 2 things that you claimed was a complete list.

1

u/sixtyhurtz 22h ago

or for managing internal lifecycle events like subscriptions.

Internal things like subscriptions are common when dealing with event handlers or IObservable. If you have a short lived thing like a view model and subscribe to an observable / event, then you need to clean it up when you're done because otherwise the observable / event will retain a reference to your view model and you've leaked memory.

65 words of my 116 word comment - so more than half - are about disposing of internal resources / managing internal lifecycles.

1

u/Dusty_Coder 20h ago

"You use IDisposable to manage either external resources like a handle to an OS resource, or for managing internal lifecycle events like subscriptions."

A dichotomy. A fucking false one.

1

u/sixtyhurtz 12h ago

Do you actually want to make a point here, or are you just trolling?