Search code examples
c#disposec#-7.0

C# 7.0 – Discards and IDisposable out argument


Is Discards feature correctly works with IDisposable objects?

Is it call Dispose(); when its needed?


I have a code:

Boolean existing = Mutex.TryOpenExisting(name: key, rights: MutexRights.ReadPermissions, result: out Mutex _);

Here I need only existing variable value.

As you see, I'm trying to use "discard" variable here, but I'm not sure this is correct usage in this case or not.

Because of Mutex obj implements IDisposable.

So which way will be correct in this case? this:

Boolean existing = Mutex.TryOpenExisting(name: key, rights: MutexRights.ReadPermissions, result: out Mutex _);

or this:

Mutex mutex; 
Boolean existing = Mutex.TryOpenExisting(name: key, rights: MutexRights.ReadPermissions, result: mutex);
mutex.Dispose();

Solution

  • I have created a test application to check @CamilioTerevinto answer.

    A simple winforms app with a method:

    public bool TestMethod(out Image bmp)
    {
        Thread.Sleep(3000);
    
        bmp = Bitmap.FromFile(@"C:\Users\UKS\Desktop\2000x2000pixels.bmp");
    
        Thread.Sleep(1000);
    
        return true;
    }
    

    Let's try a code:

    public Form1()
    {
        InitializeComponent();
        Image img;
        var a = TestMethod(out img);
        img.Dispose();
    }
    

    enter image description here

    We see an expected behavior -- image was disposed and memory was free.

    Let's try next code:

    public Form1()
    {
        InitializeComponent();
        var a = TestMethod(out _);
    }
    

    test 2

    As we see, image wasn't disposed. Memory wasn't free.

    So Discard doesn't call Dispose(); method.

    Let's try few more tests:

    Construction:

    var a = TestMethod(out _.Dispose());
    

    Will not work. It's tell's that _ doesn't exist in current context.

    Contstruction:

    var a = TestMethod(out _);
    _.Dispose();
    

    Will do the same result.

    So....

    Discards doesn't work properly with IDisposable out argument correctly. You need to call .Dispose() explicitly.