views:

102

answers:

3

I'm trying to use a generic class in a using statement but the compiler can't seem to treat it as implementing IDisposable.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;

namespace Sandbox
{
    public sealed class UnitOfWorkScope<T> where T : ObjectContext, IDisposable, new()
    {
        public void Dispose()
        {
        }
    }

    public class MyObjectContext : ObjectContext, IDisposable
    {
        public MyObjectContext() : base("DummyConnectionString") { }

        #region IDisposable Members

        void IDisposable.Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class Consumer
    {
        public void DoSomething()
        {
            using (new UnitOfWorkScope<MyObjectContext>())
            {
            }
        }
    }
}

Compiler error is:

Error 1 'Sandbox.UnitOfWorkScope<Sandbox.MyObjectContext>': type used in a using statement must be implicitly convertible to 'System.IDisposable'

I implemented IDisposable on UnitOfWorkScope (and to see if that was the problem, also on MyObjectContext).

What am I missing?

+10  A: 

I implemented IDisposable on UnitOfWorkScope

No, you didn't. You specified that your T should implement IDisposable.

Use this syntax:

public sealed class UnitOfWorkScope<T> : IDisposable where T : ObjectContext, IDisposable, new()

So first, declare what classes/interfaces UnitOfWorkScope implements (IDisposable) and then declare the constraints of T (T must derive from ObjectContext, implement IDisposable and have a parameterless constructor)

Michael Stum
+1 - exactly. UnitOfWorkScope is NOT implementing IDisposable in the given source.
TomTom
+4  A: 

You've specified that the T in UnitOfWorkScope<T> must implement IDisposable, but not that UnitOfWorkScope<T> itself implements IDisposable. I think you want this:

public sealed class UnitOfWorkScope<T> : IDisposable
    where T : ObjectContext, IDisposable, new()
{
    public void Dispose()
    {
        // I assume you'll want to call IDisposable on your T here...
    }
}
Dean Harding
+3  A: 

You've implemented IDisposable on everything except what you need to implement it on: UnitOfWorkScope<T> implements a Dispose method but never implements IDisposable. The where clause applies to T, not to the class.

Eric Lippert