繁体   English   中英

C# 协变转换失败

[英]C# Failing Covariant Cast

我正在尝试创建具有一系列实现的通用表工厂之类的东西。 下面的示例是不言自明的,即使两个类型属性都标记为“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声称会生成Table<SuperRow>的实例。 这意味着,无论您从中获得什么表,您都可以添加SuperRows并读取SuperRows

但是,您的ITableFactory<ITableRow, Table<ITableRow>>声称它生成Table<ITableRows> - 人们可以将ITableRows添加到并从中读取ITableRows的表。

但是您的实际表工厂会生成Table<SuperRow> ——底层的行存储是SuperRow 你不能让别人把任何旧的ITableRow放在那里!

这就是你的演员失败的原因。

如果您摆脱“人们可以向表中添加行”位,以及人们只能读取行的 promise,您就可以解决这个问题。 那么Table的行存储是否实际上是SuperRow并不重要,因为人们无法尝试将其他类型的行放入其中。

您可以通过使Table<T>协变来做到这一点。 但是正如您所指出的,类不能是协变的,只能是接口。 所以你需要一个ITable<out T>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM