3

If I write the following code:

public void Execute()
{
    var stream = new MemoryStream();
    ...
}

then code analysis will flag this as:

Warning 1 CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()', call System.IDisposable.Dispose on object 'stream' before all references to it are out of scope. C:\Dev\VS.NET\DisposeTest\DisposeTest\ServiceUser.cs 14 DisposeTest

However, if I create a factory pattern, I still might be required to dispose of the object, but now FxCop/Code Analysis doesn't complain. Rather, it complains about the factory method, not the code that calls it. (I think I had an example that did complain about the factory method, but the one I post here doesn't, so I struck that out)

Is there a way, for instance using attributes, to move the responsibility of the IDisposable object out of the factory method and onto the caller instead?

Take this code:

public class ServiceUser
{
    public void Execute()
    {
        var stream = StreamFactory.GetStream();
        Debug.WriteLine(stream.Length);
    }
}

public static class StreamFactory
{
    public static Stream GetStream()
    {
        return new MemoryStream();
    }
}

In this case, there are no warnings. I'd like FxCOP/CA to still complain about my original method. It is still my responsibility to handle that object.

Is there any way I can tell FxCOP/CA about this? For instance, I recently ventured into the annotation attributes that ReSharper has provided, in order to tell its analysis engine information it would otherwise not be able to understand.

So I envision something like this:

public static class StreamFactory
{
    [return: CallerResponsibility]
    public static Stream GetStream()
    {
        return new MemoryStream();
    }
}

Or is this design way off?

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825

1 Answers1

4

There is a difference between FxCop 10 (which ships with the Windows 7 and .NET 4.0 SDK) and Code Analysis 2010 (which ships with Visual Studio Premium and higher). Code Analysis 2010 has a set of additional rules, which includes a highly improved version of the IDisposable rules.

With Code Analysis 2010 under Visual Studio Premium, the Factory isn't being flagged (as the rule now sees the IDisposable variable is returned to the calling method). The Receiving method, however, isn't flagged either, due to one of the corner case exceptions to the rule. There is a list of method names that will cause the rule to trigger. If you rename your GetStream method to CreateStream, suddenly the rule will trigger:

Warning 4   CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()',
call System.IDisposable.Dispose on object 'stream' before all references to it are out
of scope.   BadProject\Class1.cs    14  BadProject

I was unable to locate the list of method pre-fixes that will work. I've tried a few and Create~, Open~ trigger the rule, many others that you might expect to work, don't, including Build~, Make~, Get~.

Additionally there is a long list of bugs surrounding this rule. The rule was altered in Visual Studio 2010 to trigger fewer false positives, but now it sometimes misses items it should have flagged (and would have flagged in the previous version). There wasn't enough time to fix the rules in the Visual Studio 2010 time frame (check the bug report comments).

With the upcoming Roslyn compilers, Code Analysis will probably see a major upgrade, until then there are only minor updates to be expected. The current build of Visual Studio Dev11 does not trigger where you want it.

So concluding, no your attribute wouldn't help much, as the rule already detects that you're passing the IDisposable as a return value. Thus Code Analysis knows it's not good to dispose it before returning. If you're using the undocumented naming rules, the rule will trigger. Maybe an attribute could extend the naming rules, but I'd rather have Microsoft would actually fix the actual rule.

I created a connect bug requesting the naming guideline to be documented in the rules documentation.

Comment from Microsoft:

Posted by Microsoft on 1/19/2012 at 10:41 AM Hello,

Thank you for taking the time to investigate this and file the request for the documentation update. However after some discussion with our documentation team, we have decided to not document the naming convention as you requested.

As you indicated on the stackoverflow thread, there have historically been a lot of reliability issues with this rule, and keying off of the names was an internal implementation detail added to try to reduce the number of false positives. However this is not considered prescriptive guidance for how developers should name their methods, it was added after a survey of common coding practices. We believe the long-term fix is to improve the reliability of the rule, not add naming guidance to our public documentation based on internal implementation details that will continue to change as the rule is improved.

Best Regards, Visual Studio Code Analysis Team

jessehouwing
  • 106,458
  • 22
  • 256
  • 341