我有一个名为Structure<A, E, B, V, K>
的类,该类通过接口继承了通用方法FireEdges<TA, TE, TB, TV, TK>(Func<TE, TK> transformer)
。
我想根据传递给FireEdges
的类型是否与实例类型匹配来运行不同的代码。
例如,如果我有:
Structure<int, int, int, int, int> s = new ...
然后,如果我致电s.FireEdges<int, int, int, int, int>(Func<int, int> transformer)
例如,它应该运行与我调用s.FireEdges<A, B, C, D, E>(Func<B, E> transformer)
相比单独的代码。
为此,我尝试执行以下操作:
public override void FireEdges<TA, TE, TB, TV, TK>(Func<TE, TK> transformer) {
if (typeof(TE) == typeof(E) && ... ) //Check other types too
foreach (E e in Edges)
e.Target.Data = transformer(e);
else
//Do something else since not all types match
}
我遇到此错误:
参数类型“ E”不可分配给参数类型“ TE”
即使我只是在检查它们确实是相同类型之后才尝试分配。
很明显我做错了什么,但我不知道这可能是什么。
谢谢
答案 0 :(得分:3)
我想根据传递给FireEdges的类型是否与实例类型匹配来运行不同的代码。
从不这样做。如果这样做,您的代码不是 generic 。泛型旨在成为泛型,因此得名。
很明显我做错了什么,但我不知道这可能是什么。
现在你知道了。 如果您正在对泛型进行类型测试,几乎可以肯定是做错了。
正如其他答案所指出的那样,如果您沉迷于以这种方式滥用泛型,则可以对对象引入强制类型转换,然后对“出站”类型强制类型转换以解决错误。 这可能会带来装箱惩罚,因为从历史上看,抖动并未优化T->装箱的T-> T代码路径。在这种情况下,也许抖动已得到固定以生成最佳代码,但我会进行检查。
答案 1 :(得分:0)
问题是只有您知道参数的类型为TE
,而编译器却不知道。您只需要强制转换:
e.Target.Data = transformer((TE)(object)e);
答案 2 :(得分:0)
仅适用于几种类型的泛型并不是真正的 generic ,它只是某种特定类型,将自己隐藏在通用皮中。因此,如果您的TE
参数仅适用于E
类型的实例,则不应使用泛型。而是使用可能具有类型的普通方法,例如ReadInt
,ParseString
或其他类型,
除此之外,在编译时中没有任何东西可以约束E
的类型为TE
,只有在 runtime < / em>。这使编译器无法知道如何从TE
生成E
。您必须使用演员表提供该信息。但是,由于这些类型之间没有关系,尤其是TE
甚至可能是值类型,因此您可能必须在以下情况前强制转换为object
:
var te = (TE)(object)e;