参数类型“ E”不可分配给参数类型“ TE”

时间:2018-09-28 21:23:50

标签: c# generics types

我有一个名为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”

即使我只是在检查它们确实是相同类型之后才尝试分配。

很明显我做错了什么,但我不知道这可能是什么。

谢谢

3 个答案:

答案 0 :(得分:3)

  

我想根据传递给FireEdges的类型是否与实例类型匹配来运行不同的代码。

从不这样做。如果这样做,您的代码不是 generic 。泛型旨在成为泛型,因此得名。

  

很明显我做错了什么,但我不知道这可能是什么。

现在你知道了。 如果您正在对泛型进行类型测试,几乎可以肯定是做错了

正如其他答案所指出的那样,如果您沉迷于以这种方式滥用泛型,则可以对对象引入强制类型转换,然后对“出站”类型强制类型转换以解决错误。 这可能会带来装箱惩罚,因为从历史上看,抖动并未优化T->装箱的T-> T代码路径。在这种情况下,也许抖动已得到固定以生成最佳代码,但我会进行检查。

答案 1 :(得分:0)

问题是只有您知道参数的类型为TE,而编译器却不知道。您只需要强制转换:

e.Target.Data = transformer((TE)(object)e);

答案 2 :(得分:0)

仅适用于几种类型的泛型并不是真正的 generic ,它只是某种特定类型,将自己隐藏在通用皮中。因此,如果您的TE参数仅适用于E类型的实例,则不应使用泛型。而是使用可能具有类型的普通方法,例如ReadIntParseString或其他类型,

除此之外,在编译时中没有任何东西可以约束E的类型为TE,只有在 runtime < / em>。这使编译器无法知道如何从TE生成E。您必须使用演员表提供该信息。但是,由于这些类型之间没有关系,尤其是TE甚至可能是值类型,因此您可能必须在以下情况前强制转换为object

var te = (TE)(object)e;