[英]Any workarounds for structs failing to cast to object when the struct is the covariant type of a generic object being being casted in 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.