C# 7.0 – Discards and IDisposable out argument
Asked Answered
F

2

8

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();
Flinger answered 15/12, 2018 at 17:58 Comment(3)
Well, _.Dispose(); is not wrong, but reviewed behind the door on the right.Mastaba
I will try _.Dispose(); code a little bit later, thanks :)Flinger
Do try it, then refactor _ to mutex.Mastaba
F
9

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.

Flinger answered 15/12, 2018 at 20:41 Comment(3)
What about something like: using (_ = ZipFile.Open(filename, ZipArchiveMode.Update)) { } To create an archive if it doesn't exist?Cockaigne
do the test and write here your results. But even if this will work - this will work by the same way with discard or without discard. Just because of using.Flinger
Yes it does get disposed or you could omit the discard and get same result. I made a question which turned out to be a duplicate. https://mcmap.net/q/1325927/-will-the-discard-variable-_-call-dispose-when-put-in-a-using-statement-duplicate/2229933Cockaigne
D
4

As far as I understand,

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

will discard the Mutex generated by the call. Discarding it does not mean that some method, like Dispose(), will be called.
You need to call .Dispose() explicitly.

I'd just continue using

Mutex mutex; 
Boolean existing = Mutex.TryOpenExisting(name: key, rights: MutexRights.ReadPermissions, result: mutex);
mutex.Dispose();
Downstream answered 15/12, 2018 at 18:13 Comment(1)
I did a check. You're absolutely right. It doesn't dispose objects.Thanks a lot!Flinger

© 2022 - 2024 — McMap. All rights reserved.