0

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?

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yep. I need to read more on covariance and contravariance it appears. Thanks.
0

Check out Eric Lippert's blog posts on Covariance and Contravariance. It is a ten part series I think.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.