Domanda

I've got following piece of code in a singleton-like class:

    private readonly Lazy<IWindsorContainer> LazyContainer =
        new Lazy<IWindsorContainer>(() => new WindsorContainer().Install(new WindsorInstaller()));

and given that WindsorContainer indeed needs releasing I do that later in the host so naturally I'd like to suppress the naughty Microsoft.Reliability warning about IDisposable probably not released. The problem is that it's created inside the lambda and looks like SuppressMessage has no effect on it and I definitely do not want it the on entire class.

I've came this around with suppressing attribute on a constructor. But still not perfectly happy with that.

Am I missing something or SuppressMessage is not catching up with evolution of the c#?

È stato utile?

Soluzione

I think it is considering the possibility that the call to Install() fails and then the container, which is not assigned to any variable yet, is not disposed. You can add a try/catch there, making the expression much more verbose but compliant with the rule like (not tested, but you'd get the idea):

private readonly Lazy<IWindsorContainer> LazyContainer =
    new Lazy<IWindsorContainer>(() => { 
        var container = new WindsorContainer();
        try { container.Install(new WindsorInstaller())); }
        catch { using(container) {} throw; }
        return container; });

Altri suggerimenti

As fsimonazzi correctly pointed out this is about call new WindsorContainer().Install(new WindsorInstaller()) which uses the IDisposable before it's saved into member variable (and thus gives no guarantee that it will ever be).

For myself I've decided to refactor the thing into following:

class Program : IDisposable
{

    private Disposo _disposo = new Disposo();
    //private Disposo _disposo = new Disposo().Yeah(); // this will cause warning

    public Program()
    {
        _disposo.Yeah(); // this will not
    }

    public void Dispose()
    {
        if (_disposo != null)
        {
            _disposo.Dispose();
            _disposo = null;
        }
    }

    static void Main(string[] args)
    {
        using (var p = new Program()) { }
    }
}

class Disposo : IDisposable
{
    public void Dispose() { }

    public Disposo Yeah() { return this; }
}

and somewhere there's

    private static readonly Lazy<Program> LazyInstance = new Lazy<Program>();

Moral? Despite claims that "CA2000: Dispose objects before all references to it are out of scope." is broken and can be ignored and suppressed, it's not always the case.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top