Reputation: 6868
Suppose I have a concrete class - 'Giraffe' that implements 'IMammal'. In my scenario, I can create a generic repository and factory like so:
public MammalFactory : IMammalFactory
{
public IMammalRepository<T> GetMammalRepo<T>() where T: IMammal, new()
{
return new MammalRepository<T>();
}
}
MammalRepository can now be of type Giraffe or Antelope as long as they both implement IMammal. So far, so good.
However, I can't use an expression like this (won't compile and cannot cast):
Func<IMammalRepository<IMammal>> = () => this.factory.GetMammalRepo<Giraffe>();
I have a method that is very similar between my classes and I want to factor them down to something like:
//called from different implementations
public void FeedAnimalInternal(Func<IMammalRepository<IMammal>> repo, Action<IMammal> doIt)
{
var animalRepo = repo();
var animals = animalRepo.GetAnimals(); //might be giraffe or might be something else
foreach (var animal in animals) { doIt(animal); }
}
First, why won't the Func<> (first one) compile? Is this a covariance thing? Next, any idea how I can accomplish something similar to what I am trying to do?
Upvotes: 0
Views: 92
Reputation: 1128
Check out Eric Lippert's blog posts on Covariance and Contravariance. It is a ten part series I think.
Upvotes: 0
Reputation: 78850
Yes, it's a covariance thing. If you define IMammalRepository
like this:
public interface IMammalRepository<out T> where T : IMammal
{
// ...
}
This should solve your problem.
Upvotes: 3