gpt4 book ai didi

C# 失败的协变转换

转载 作者:太空宇宙 更新时间:2023-11-03 20:48:07 25 4
gpt4 key购买 nike

我正在尝试创建具有一系列实现的通用表工厂之类的东西。下面的示例是不言自明的,即使两个类型属性都标记为“out”,最终转换也不起作用。我想,问题是 Table 不是接口(interface),这会破坏 Actor 阵容。但它不应该是真正的接口(interface),尤其不是协变的。任何想法如何正确转换?绝对不想用反射来使用方法。

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> s -- 底层行存储是 SuperRow .你不能让别人放任何旧的 ITableRow在那里!

这就是您的类型转换失败的原因。

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

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

关于C# 失败的协变转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58530755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com