Reputation: 740
I have searched through several posts on the problem I am facing and I have found most similiar topic here
However, here we have a class as type in generic interface casting, and as I checked class SqlCommand inherits from DbCommand which implements IDbCommand. My example: We have a Processor class which let's say have method Process. Processor contains a property which is an interface of generic type described below.
public class Processor
{
IDbTools<IDbCommand> DbTools {get; set;}
public Processor() {}
public void Process()
{
DbTools = (IDbTools<IDbCommand>)new Tools();
DbTools.PrepareAndExecuteQuery();
}
}
public class Tools : IDbTools<SqlCommand>
{
public void PrepareAndExecuteQuery(SqlCommand command);
}
public interface IDbTools<in TCommand>
where TCommand: IDbCommand
{
void PrepareAndExecuteQuery(TCommand command);
}
In this example, we will recieve an InvalidCastException, without compilation error. I don't understand why this is happening if SqlCommand inherits from DbCommand and it implements IDbCommand.
The approach that i made to make it works looks like this:
public class Processor<TCommand>
where TCommand: IDbCommand, new()
{
IDbTools<TCommand> DbTools {get; set;}
public Processor() {}
public void Process()
{
DbTools = (IDbTools<TCommand>)new Tools();
DbTools.PrepareQuery();
}
}
public class Tools : IDbTools<SqlCommand>
{
void PrepareAndExecuteQuery(SqlCommand command);
}
public interface IDbTools<TCommand>
where TCommand: IDbCommand
{
void PrepareAndExecuteQuery(TCommand command);
}
So my question is, why is it happening like that. Of course if we would implement
Tools : IDbTools<IDbCommand>
everything would work, but why it isn't in this scenario..
EDIT: I am attaching sample at ideone.com: Code where is the same code just for copy past purposes into new project. Attached required namespaces.
Also adding the in clause, which isn't fixing the issue.
Upvotes: 2
Views: 1276
Reputation: 1079
You need to declare your IDbTools<>
interface with the in keyword
public interface IDbTools<in TCommand>
where TCommand: IDbCommand
{
void PrepareAndExecuteQuery(TCommand command);
}
See here about Covariance and Contravariance, Microsoft can explain it a lot better than I can
Upvotes: 1