Home > database >  Including a generic type parameter in interface, constraint by an interface
Including a generic type parameter in interface, constraint by an interface

Time:05-19

I am stuck on the usage of an implementation that is constraint by an interface. My usage is intuitive to me, but does not compile so I am misunderstanding something.

My interfaces:

interface IEntity
{
    int ExampleMethod(IContext<IFooBar> context);
}

interface IContext<T> where T : class, IFooBar
{
    T FooBar { get; set; }
}

interface IFooBar
{
    int Value { get; }
}

My implementations:

class Entity : IEntity
{
    public int ExampleMethod(IContext<IFooBar> context)
    {
        return context.FooBar.Value;
    }
}

class Context : IContext<FooBar>
{
    public FooBar FooBar { get; set; }
}

class FooBar : IFooBar
{
    public int Value { get { return 10; } }
}

Usage of Entity class, where problem is thrown

class UsageOfEntity
{
    public UsageOfEntity()
    {
        var context = new Context();
        var entity = new Entity();

        int result = entity.ExampleMethod(context);
    }
}

The usage of instance context throws an error:

Argument 1: cannot convert from 'Context' to 'IContext<IFooBar>'

How do I constrain the generic type parameter such that my implementation can be used?

CodePudding user response:

Context is an IContext<FooBar> not an IContext<IFooBar>.

Because OP has indicated in the comments that IContext<T>.FooBar only needs to be read-only, T can be made covariant:

interface IContext<out T>
where T : class, IFooBar
{
    T FooBar { get; }
}

Now, because FooBar implements IFoobar, it is valid to use a IContext<FooBar> in place of a IContext<IFooBar>:

CodePudding user response:

The problem in your code is that you are trying to convert Context to Type IContext just as your error tells you.

{
    public UsageOfEntity()
    {
        var context = new Context();
        var entity = new Entity();

        int result = entity.ExampleMethod(context);
    }
}

You are trying to pass Context to IContext in this line

entity.ExampleMethod(context);

You should make the Type passed in ExampleMethod() Context<FooBar>. I would also like to point out that making an interface for a POCO class is unnecessary, just keep it a normal class.

Your code should look like this:

class Entity : IEntity
{
    public int ExampleMethod(Context<FooBar> context)
    {
        return context.FooBar.Value;
    }
}

interface IEntity
{
    int ExampleMethod(IContext<IFooBar> context);
}
  • Related