0

I have a much more complicated issue, but I've boiled it down to the following simple example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            IFactory<IProduct> factory = new Factory();
        }
    }

    class Factory : IFactory<Product>
    {

    }

    class Product : IProduct
    {

    }

    interface IFactory<T> where T : IProduct
    {

    }

    interface IProduct
    {

    }
}

All is well and dandy... except that I get this error.

Error 1 Cannot implicitly convert type Sandbox.Factory to Sandbox.IFactory<Sandbox.IProduct>. An explicit conversion exists (are you missing a cast?) c:\~~\Program.cs 12 42 Sandbox

Anyone willing to provide insight into why this is the case? I'm sure Jon Skeet or Eric Lippert could explain in a heartbeat why this is, but there has to be someone that not only understands WHY this can't be inferred, but can explain how best to solve this situation.

Follow up question here

Community
  • 1
  • 1
Firoso
  • 6,647
  • 10
  • 45
  • 91
  • As it turns out, Eric Lippert and Jon Skeet have explained this in a heartbeat quite a number of times. You'll probably trip and find one such explanation if you search for `interface + covariance`. – Anthony Pegram Jun 17 '11 at 18:57
  • 1
    Follow-up questions should be asked as separate questions (Do link them together though.) – Ben Voigt Jun 17 '11 at 19:14
  • The answer to your follow-up question is that *covariance requires that return types be covariant* in the type parameter. `List` isn't covariant, you can't treat a `List` as a `List`, because `List` has no `Add(IProduct)` method. You could return `IEnumerable` though, and it would work, since `IEnumerable` is usable anywhere `IEnumerable` is expected. – Ben Voigt Jun 17 '11 at 19:17

1 Answers1

3

It is because Factory is an IFactory< Product> and what you are assigning it to is a IFactory< IProduct>, and since IFactory is not covariant, you cannot cast a generic of subtype to a generic of supertype.

Try making IFactory< out T>, which should make the following assignment work.

EDIT:

@Firoso, in your factory interface you are trying to create a list, in which you can write to. If your interface is covariant you can not write to anything, because of the following:

List<object> list = new List<string>(); //This is not possible by the way
list.Add(new {}); //Will fail here because the underlying type is List<string> 

You should ignore covariance in your case and just create assign to an IFactory<Product>instead or change factory to inherit IFactory<IProduct>instead, I recommend the latter but it is up to you

Yet Another Geek
  • 4,251
  • 1
  • 28
  • 40