C# 接口继承和泛型接口强制显式转换?

C# 接口继承和泛型接口强制显式转换?,c#,generics,inheritance,interface,type-inference,C#,Generics,Inheritance,Interface,Type Inference,我有一个更复杂的问题,但我将其归结为以下简单的例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Sandbox { class Program { static void Main(string[] args) { IFactory<IProduct> facto

我有一个更复杂的问题,但我将其归结为以下简单的例子:

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
    {

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
名称空间沙盒
{
班级计划
{
静态void Main(字符串[]参数)
{
i工厂=新工厂();
}
}
类别工厂:IFactory
{
}
类别产品:IPProduct
{
}
接口IFactory,其中T:IPProduct
{
}
接口IPProduct
{
}
}
一切都很好,很漂亮。。。除了我得到这个错误

错误1无法将类型
Sandbox.Factory
隐式转换为
Sandbox.IFactory
。存在显式转换(是否缺少转换?)c:\~\Program.cs 12 42沙盒

是否有人愿意深入了解这种情况的原因?我相信Jon Skeet或Eric Lippert可以马上解释为什么会这样,但必须有人不仅理解为什么不能推断,而且能够解释如何最好地解决这种情况


后续问题

这是因为
工厂
是一个
IFactory
,而您分配给它的是一个
IFactory
,并且由于
IFactory
不是,所以不能将子类型的泛型强制转换为超类型的泛型

尝试制作
IFactory
,这将使以下任务正常工作

编辑

@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> 
List List=新列表()//顺便说一句,这是不可能的
添加(新的{})//将在此失败,因为基础类型是List

在您的案例中,您应该忽略协方差,只需创建分配给
IFactory
,或者将工厂更改为继承
IFactory
,我推荐后者,但这取决于您

这是因为
工厂
是一个
IFactory
,您分配给它的是一个
IFactory
,并且由于
IFactory
不是,所以不能将子类型的泛型强制转换为超类型的泛型

尝试制作
IFactory
,这将使以下任务正常工作

编辑

@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> 
List List=新列表()//顺便说一句,这是不可能的
添加(新的{})//将在此失败,因为基础类型是List

在您的案例中,您应该忽略协方差,只需创建分配给
IFactory
,或者将工厂更改为继承
IFactory
,我建议使用后者,但这取决于您自己,Eric Lippert和Jon Skeet已经多次解释了这一点。如果搜索
接口+协方差
,您可能会绊倒并找到一个这样的解释。后续问题应该作为单独的问题进行提问(但一定要将它们链接在一起)。后续问题的答案是协方差要求返回类型在类型参数中是协方差的<代码>列表不是协变的,您不能将
列表
视为
列表
,因为
列表
没有
添加(IPProduct)
方法。但是,您可以返回
IEnumerable
,它会起作用,因为
IEnumerable
可以在任何预期的
IEnumerable
位置使用。事实证明,Eric Lippert和Jon Skeet已经多次解释了这一点。如果搜索
接口+协方差
,您可能会绊倒并找到一个这样的解释。后续问题应该作为单独的问题进行提问(但一定要将它们链接在一起)。后续问题的答案是协方差要求返回类型在类型参数中是协方差的<代码>列表不是协变的,您不能将
列表
视为
列表
,因为
列表
没有
添加(IPProduct)
方法。您可以返回
IEnumerable
,它会工作,因为
IEnumerable
可以在任何需要
IEnumerable
的地方使用。哦,这是一个协方差问题,这很有意义:-p这更接近我的预期答案,请在上面的链接上继续,我会将其标记为答案。其他人给出的解释是可以的,只是接受它们,但谢谢:)哦,这是一个协方差问题,这是有意义的:-p这更接近我的预期答案,请在上面的链接上继续,我会将其标记为答案。其他人给出的解释是可以的,接受它们,但谢谢你:)