Resources returned by properties, and disposal

H

Harlan Messinger

I'm trying to figure out how this works: I have an app that will set and
read various values in the Windows registry under a key particular to
the application.

Suppose I have this:

public class PersisterBase
{
...
public string OrganizationName { get; set; }
public string ApplicationName { get; set; }

public RegistryKey ApplicationRegistryKey
{
get
{
return
Registry.CurrentUserOpenSubKey("Software").CreateSubKey(OrganizationName).CreateSubKey(ApplicationName);
}
}
...
}

Elsewhere suppose I have:

PersisterBase pbase = new PersisterBase();
pbase.OrganizationName = "Acme";
pbase.Application = "MyApp";
string value1 = pbase.ApplicationRegistryKey.GetValue("value1");
string value2 = pbase.ApplicationRegistryKey.GetValue("value2");
string value3 = pbase.ApplicationRegistryKey.GetValue("value3");

Doesn't this leave me with three open, undisposed registry key objects
or locks or whatever, on the application registry key?

Does it do any good if I stick the three final assignments into a
using(pbase.ApplicationRegistryKey) block? I don't think so.

I thought of doing this:

private RegistryKey applicationRegistryKey = null;
public RegistryKey ApplicationRegistryKey
{
get
{
if (applicationRegistryKey == null)
applicationRegistryKey =
Registry.CurrentUserOpenSubKey("Software").CreateSubKey(OrganizationName).CreateSubKey(ApplicationName);

return applicationRegistryKey;
}
}

so that the key would only be opened once, but then that means that that
one instance of it is being held open indefinitely--and, still, when is
it closed or disposed?

Is the only way to deal with this to place on the developer using the
PersisterBase the responsibility of knowing to use it like this:

PersisterBase pbase = new PersisterBase();
pbase.OrganizationName = "Acme";
pbase.Application = "MyApp";
using (RegistryKey key = pbase.ApplicationRegistryKey)
{
string value1 = key.GetValue("value1");
string value2 = key.GetValue("value2");
string value3 = key.GetValue("value3");
}

or is there some way to spare the downstream developer the need to write
his code this way?
 
H

Harlan Messinger

Peter said:
[...]
public RegistryKey ApplicationRegistryKey
{
get
{
return
Registry.CurrentUser.OpenSubKey("Software").CreateSubKey(OrganizationName).CreateSubKey(ApplicationName);

}
}
[...]
string value1 = pbase.ApplicationRegistryKey.GetValue("value1");
string value2 = pbase.ApplicationRegistryKey.GetValue("value2");
string value3 = pbase.ApplicationRegistryKey.GetValue("value3");

Doesn't this leave me with three open, undisposed registry key objects
or locks or whatever, on the application registry key?

No, it doesn't. It leaves you with nine undisposed RegistyKey objects

Ha. Well, that makes sense! I hadn't thought of that.
(there's actually technically twelve, but the "CurrentUser" RegistryKey
object doesn't ever actually close, being a "system key", so you don't
need to dispose it).
Does it do any good if I stick the three final assignments into a
using(pbase.ApplicationRegistryKey) block? I don't think so.

Why don't you think so? Assuming each assignment gets its own using()
statement, it should work fine and accomplish exactly what you need to
accomplish, at least for the RegistryKey object returned by the property
(it won't help for the two you just leave dangling inside the property
getter though).
[snip]
or is there some way to spare the downstream developer the need to
write his code this way?

One possibility would be to write a method instead of a property, to
which you can pass the name of the value you want to retrieve. Then the
method can dispose all three of the RegistryKey objects it creates,
before returning the _string_ value that was retrieved.

I guess it would have to be that way to keep the client from dealing
with closing the key, but it makes more sense to hold open the one
registry key to which all the values were going to be written. I suppose
I will clean up the property itself, so that the higher-level keys are
closed after they've been used, and then make the client responsibility
for closing the key given to it.
If you have other types of values you want to retrieve as well, just
create similar overloads as necessary.

Then the "downstream developer" simply calls the method with the name of
the value he wants, and the RegistryKey objects are never seen by him,
nor does he need to worry about disposing them.
Thanks for helping me think it through.
 
H

Harlan Messinger

Peter said:
[...]
public RegistryKey ApplicationRegistryKey
{
get
{
return
Registry.CurrentUser.OpenSubKey("Software").CreateSubKey(OrganizationName).CreateSubKey(ApplicationName);

}
}
[...]
string value1 = pbase.ApplicationRegistryKey.GetValue("value1");
string value2 = pbase.ApplicationRegistryKey.GetValue("value2");
string value3 = pbase.ApplicationRegistryKey.GetValue("value3");

Doesn't this leave me with three open, undisposed registry key objects
or locks or whatever, on the application registry key?

No, it doesn't. It leaves you with nine undisposed RegistyKey objects
(there's actually technically twelve, but the "CurrentUser" RegistryKey
object doesn't ever actually close, being a "system key", so you don't
need to dispose it).
Does it do any good if I stick the three final assignments into a
using(pbase.ApplicationRegistryKey) block? I don't think so.

Why don't you think so? Assuming each assignment gets its own using()
statement, it should work fine and accomplish exactly what you need to
accomplish, at least for the RegistryKey object returned by the property
(it won't help for the two you just leave dangling inside the property
getter though).

Actually not, because the "using" construct will hold on to the instance
of the key generated by the call made from between the parentheses,
while the call from the assignment (even if there were only one
assignment within the "using" block) would generate another instance
that wouldn't be disposed.
 
H

Harlan Messinger

Peter said:
[...]
Does it do any good if I stick the three final assignments into a
using(pbase.ApplicationRegistryKey) block? I don't think so.

Why don't you think so? Assuming each assignment gets its own
using() statement, it should work fine and accomplish exactly what
you need to accomplish, at least for the RegistryKey object returned
by the property (it won't help for the two you just leave dangling
inside the property getter though).

Actually not, because the "using" construct will hold on to the
instance of the key generated by the call made from between the
parentheses, while the call from the assignment (even if there were
only one assignment within the "using" block) would generate another
instance that wouldn't be disposed.

If you think it won't work, it's because you're not writing it
correctly. This is how you _should_ write it, using "using":

string value1;

using (RegistryKey key = pbase.ApplicationRegistryKey)
{
value1 = key.GetValue("value1");
}

Yes, I used that construction later in my original message. This one
happens to be the one you were responding to, though! Anyway, we're on
the same page.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top