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);
}
