C# C协变强制转换

C# C协变强制转换,c#,generics,covariance,variance,C#,Generics,Covariance,Variance,我正在尝试创建一个类似于通用表工厂的东西,它有一系列的实现。下面的示例是不言自明的,即使两个类型属性都标记为“out”,最后的强制转换也不起作用。我想,问题是Table不是一个接口,这破坏了演员阵容。但它不是真正的接口,尤其不是协变的。你知道如何正确地投下它吗?绝对不想使用反射来使用方法 interface ITableRow { } class Table<T> where T : ITableRow { } interface ITableFactory<out TRo

我正在尝试创建一个类似于通用表工厂的东西,它有一系列的实现。下面的示例是不言自明的,即使两个类型属性都标记为“out”,最后的强制转换也不起作用。我想,问题是Table不是一个接口,这破坏了演员阵容。但它不是真正的接口,尤其不是协变的。你知道如何正确地投下它吗?绝对不想使用反射来使用方法

interface ITableRow { }

class Table<T> where T : ITableRow { }

interface ITableFactory<out TRow, out TTable>
    where TRow : ITableRow
    where TTable : Table<TRow>
{
    TTable CreateTable();
}

// example implementation:

class SuperRow : ITableRow { }

class SuperTableFactory : ITableFactory<SuperRow, Table<SuperRow>>
{
    public Table<SuperRow> CreateTable() { throw new NotImplementedException(); }
}

// run:

class VarianceTest
{
    public static void Test()
    {
        var factory = Activator.CreateInstance(Type.GetType("Snippets.Var.SuperTableFactory"));

        var casted = (ITableFactory<ITableRow, Table<ITableRow>>) factory; // cast fails
    }
}
SuperTableFactory声称生成表的实例。这意味着,无论从中得到什么表,都可以添加超行并读取超行

然而,您的ITableFactory声称它生成了人们可以向其中添加ITableRows和从中读取ITableRows的表

但实际的表工厂生成表——底层行存储是SuperRow。你不能让别人把旧的ITableRow放进去

这就是你的演员阵容失败的原因

若你们摆脱了“人们可以向表中添加行”这一点,并承诺人们只能读取行,那个么你们就可以解决这个问题。然后,表的行存储是否实际上是SuperRow并不重要,因为人们无法尝试将其他类型的行放在其中

您可以通过使表协变来实现这一点。但正如您所指出的,类不能是协变的,只能是接口。所以您需要一个ITable。

您的SuperTableFactory声称要生成表的实例。这意味着,无论从中得到什么表,都可以添加超行并读取超行

然而,您的ITableFactory声称它生成了人们可以向其中添加ITableRows和从中读取ITableRows的表

但实际的表工厂生成表——底层行存储是SuperRow。你不能让别人把旧的ITableRow放进去

这就是你的演员阵容失败的原因

若你们摆脱了“人们可以向表中添加行”这一点,并承诺人们只能读取行,那个么你们就可以解决这个问题。然后,表的行存储是否实际上是SuperRow并不重要,因为人们无法尝试将其他类型的行放在其中


您可以通过使表协变来实现这一点。但正如您所指出的,类不能是协变的,只能是接口。因此,您需要一个ITable。

Dotnetfiddle演示问题:Dotnetfiddle演示问题:最好的解释,谢谢。问题是,表格不可能真的是协变的,它有列表之类的东西。我正试图找到一种解决方法,现在制作一个工厂,在接口和实现之间有一个抽象类..对-这样人们可以添加行,所以你不能假装一个表实际上是一个表,那样人们就可以添加其他种类的行。不,他们不能添加行,但表有列定义列表,这不允许我将ITableRow标记为OUT类型:列当然也需要是协变的,所以IColumn和Columns属性不能设置为可设置的。这是最好的解释,非常感谢。问题是,表格不可能真的是协变的,它有列表之类的东西。我正试图找到一种解决方法,现在制作一个工厂,在接口和实现之间有一个抽象类..对-这样人们可以添加行,所以你不能假装一个表实际上是一个表,那样人们就可以添加其他种类的行。不,他们不能添加行,但表有列定义列表,这不允许我将ITableRow标记为OUT类型:列当然也需要是协变的,所以IColumn和Columns属性不能设置