Covariance and contravariance don't make as much sense on value types, because they are all sealed. Though it's not clear from the documentation, it is valid to use a struct
as a co/contravariant type, it's just not always useful. The documentation you reference is most likely referring to that the following is not valid:
public struct MyStruct<in T>
Contravariance means that you can do something like the following example:
IRepository<string, Base> b = //something
IRepository<string, Derived> d = b;
Since there's nothing that derives from int
, you can use an IRepository<string, int>
, but only as an IRepository<string, int>
.
Covariance means that you can do the reverse, e.g. IEnumerable<T>
is out T
, which is covariant. You can do the following:
IEnumerable<Derived> d = //something
IEnumerable<Base> b = d;
If you're trying to restrict both TKey
and T
to class
es (reference types), you should include a second restriction:
public interface IRepository<T, in TKey>
where T : class
where TKey : class