Riddick
Riddick

Reputation: 1318

c# Interfaces - Implicit Conversion Error?

If I have this interface:

public interface IFoo : IDisposable
{ 
    int PropA {get; set;}
    int PropB {get; set;}
}

And a class:

public class Foo : IFoo
{
    public int PropA {get; set;}
    public int PropB {get; set;}

    public void Dispose()
    {
        Dispose();
        GC.SuppressFinalize(this);
    }
}

Shouldn't this work without a 'Cannot Implicitly Convert' error?

    private Context context = new Context();
    private GenericRepository<IFoo> FooRepo;

    public GenericRepository<IFoo> Article
    {
        get
        {
            if (this.FooRepo == null)
            {
                this.FooRepo = new GenericRepository<Foo>(context);
            }
            return FooRepo;
        }
    }

I thought I had it right, what is the correct way to do this?

Upvotes: 2

Views: 163

Answers (2)

Eren Ers&#246;nmez
Eren Ers&#246;nmez

Reputation: 39085

What you're trying to do (assigning GenericRepository<Foo> reference to a field of type GenericRepository<IFoo>) would only work if GenericRepository<T> were covariant in its generic type parameter. For that, GenericRepository<> would be defined as:

public class GenericRepository<out T> {...} //note the "out" modifier. 

then this assignment would be OK:

this.FooRepo = new GenericRepository<IFoo>(context);

However, that won't work because covariance is limited to interfaces and delegates. So, in order to play within that limitation, you can define a covariant IGenericRepository<T> interface and use the interface instead of the class:

public interface IGenericRepository<out T> {}
public class GenericRepository<T> : IGenericRepository<T> { }

private Context context = new Context();
private IGenericRepository<IFoo> FooRepo;

public IGenericRepository<IFoo> Article
{
    get
    {
        if (this.FooRepo == null)
        {
            this.FooRepo = new GenericRepository<Foo>(context);
        }
        return FooRepo;
    }
}

Alternatively, if GenericRepository<T> implements IEnumerable you can use the Enumerable.Cast<T> method:

public IGenericRepository<IFoo> Article
{
    get
    {
        if (this.FooRepo == null)
        {
            this.FooRepo = new GenericRepository<Foo>(context).Cast<IFoo>();
        }
        return FooRepo;
    }
}

Upvotes: 3

Caleb Keith
Caleb Keith

Reputation: 816

You are trying to implicitly convert context to Foo and not it's interface. Also, is Context implementing IFoo? If it is, this should work.

Try this:

private Context context = new Context();
private GenericRepository<IFoo> FooRepo;

public GenericRepository<IFoo> Article
{
    get
    {
        if (this.FooRepo == null)
        {
            this.FooRepo = new GenericRepository<IFoo>(context);
        }
        return FooRepo;
    }
}

Upvotes: 1

Related Questions