Well, actually.the above example doesn't need the Default property in
order to reproduce the warning. That said, it's a good example, and
provides plenty to work with in terms of answering the question.
Unfortunately, I'm not there's a good _answer_.
As you're probably already aware, the bottom line issue here is that an
object is allocated, and then as far as the code analysis can tell, is not
disposed of before you no longer have a reference to it.
Of course, the object returned by the Synchronized() method in fact refers
to the original object (indeed, _is_ the original object), and so the
reference still exists, and so doesn't need to be disposed (and in fact,
cannot be). But there's no direct way for the code analyzer to know that.
It can't make assumptions about what the Synchronized() method does, and
it doesn't do any sort of called-method inspection to make its
determinations.
As far as potential resolutions go, here is a version of the code that
doesn't cause the warning:
using System;
using System.Configuration;
namespace CA2000
{
internal class Settings1 : ApplicationSettingsBase, IDisposable
{
private static Settings1 defaultInstance;
static Settings1()
{
defaultInstance = new Settings1();
defaultInstance =
(Settings1)ApplicationSettingsBase.Synchronized(defaultInstance);
}
public void Dispose()
{
}
}
}
Note that by writing the static constructor explicitly, _and_ by
assigning the original Settings1() object to your field before passing
it to the Synchronized() method, that's enough to convince code analysis
that you've let the object reference escape the constructor, and thus it
does not need to be disposed of before the constructor returns.
I find this resolution unfortunate in two ways:
. First, it would be nice if there were some way to explain to the
analyzer that in this case, passing the object reference to the
Synchronized() method does in fact preserve a reference to the object
after the constructor returns.
. Second, it concerns me that the code analysis doesn't pick up on the
fact that the "defaultInstance" field is being overwritten, which absent
any specific knowledge of the Synchronized() method (which clearly the
analyzer does not have) _should_ in fact mean that the original object
reference has been lost before the object has been disposed.
I find this second issue especially ironic, because it appears that when
the variable is a local variable (i.e. if you try to move the
initialization into a helper method with a try/catch to deal with
disposing the original object on error), the analyzer _does_ in fact pick
up on the fact that it's been overwritten, and so returning the new value
does not satisfy the analyzer with respect to the original value.
I don't really see a good way around the first issue, other than just
suppressing the warning (which is a blunt way to give the analyzer that
information). The second issue concerns me because it's possible someone
at Microsoft will eventually decide it's a bug that the analyzer doesn't
figure that out and will fix the bug, and then my proposed work-around
isn't going to help.
I think given all the above, personally I'd just suppress the warning and
be done with it. The fact is, it's a situation that given the kind of
analysis used for that rule, I think really cannot be detected as safe by
the analyzer, so you're left helping it out by suppressing the warning
explicitly.
Pete