Наследование интерфейса и общие интерфейсы вызывают явное приведение типов?

У меня гораздо более сложная проблема, но я свел ее к следующему простому примеру:

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
    {

    }
}

Все хорошо и денди... за исключением того, что я получаю эту ошибку.

Ошибка 1 Не удается неявно преобразовать тип Sandbox.Factory в Sandbox.IFactory<Sandbox.IProduct>. Существует явное преобразование (вам не хватает приведения?) c:\~~\Program.cs 12 42 Песочница

Кто-нибудь готов дать представление о том, почему это так? Я уверен, что Джон Скит или Эрик Липперт могли бы объяснить, почему это так, но должен быть кто-то, кто не только понимает, ПОЧЕМУ это нельзя вывести, но и может объяснить, как лучше всего разрешить эту ситуацию.

Последующий вопрос здесь


person Firoso    schedule 17.06.2011    source источник
comment
Как оказалось, Эрик Липперт и Джон Скит объясняли это несколько раз. Вы, вероятно, споткнетесь и найдете одно из таких объяснений, если будете искать interface + covariance.   -  person Anthony Pegram    schedule 17.06.2011
comment
Последующие вопросы следует задавать как отдельные вопросы (но не связывайте их вместе).   -  person Ben Voigt    schedule 17.06.2011
comment
Ответ на ваш дополнительный вопрос заключается в том, что ковариантность требует, чтобы возвращаемые типы были ковариантны в параметре типа. List<T> не является ковариантным, вы не можете рассматривать List<Product> как List<IProduct>, потому что List<Product> не имеет метода Add(IProduct). Однако вы можете вернуть IEnumerable<T>, и это сработает, поскольку IEnumerable<Product> можно использовать везде, где ожидается IEnumerable<IProduct>.   -  person Ben Voigt    schedule 17.06.2011


Ответы (1)


Это потому, что Factory является IFactory< Product>, а то, чему вы его назначаете, является IFactory< IProduct>, и поскольку IFactory не является ковариантный, вы не можете преобразовать общий тип подтипа в общий тип супертипа.

Попробуйте сделать IFactory< out T>, что должно заставить работать следующее задание.

ИЗМЕНИТЬ:

@Firoso, в своем заводском интерфейсе вы пытаетесь создать список, в который вы можете писать. Если ваш интерфейс является ковариантным, вы не можете ничего писать по следующим причинам:

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> 

Вы должны игнорировать ковариацию в вашем случае и просто создать назначение IFactory<Product>instead или изменить factory, чтобы наследовать IFactory<IProduct>instead, я рекомендую последнее, но это зависит от вас

person Yet Another Geek    schedule 17.06.2011
comment
о, это проблема ковариации, в этом есть смысл :-P - person Firoso; 17.06.2011
comment
Это ближе к моему предполагаемому ответу, пожалуйста, перейдите по ссылке выше, и я отмечу это как ответ. - person Firoso; 17.06.2011
comment
Объяснения, данные другими, в порядке, просто примите их, но спасибо :) - person Yet Another Geek; 18.06.2011