即使实现了所需的接口,泛型对象也需要强制转换

时间:2013-05-27 07:47:15

标签: c# .net generics interface

不要认为标题可以解释我的内容并且解释起来有点困难,所以我会让代码进行讨论。您可以将其复制+粘贴到LINQPad中并作为C#程序运行,或者在visual studio中作为常规c#项目进行必要的调整(例如:将调用转换为Dump()到Console.Writeline()等) -

请注意,如果您取消注释doStuff方法中的行,它将无法编译。

我的问题是,当generic2已经实现Iab<TA,TB>时,为什么我需要演员?这是一些协方差的事吗?我还在使用.NET 3.5。

void Main()
{
    doStuff<a,b>();
}

public void doStuff<TA, TB>()
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    Iab<TA, TB> x = null;

    x = new generic1<TA, TB>();
    x.Go().Dump();

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?)
    x = (Iab<TA, TB>) new generic2<TA>();
    x.Go().Dump();
}

public interface Ia
{}

public interface Ib
{}

public class a : Ia
{}

public class b : Ib
{}

public interface Iab<TA,TB>
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    string Go();
}

public class generic1<TA, TB> : Iab<TA,TB>
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    public string Go()
    {
        return "generic Base called";
    }
}

public class generic2<TA> : Iab<TA,b>
where TA : class, Ia, new()
{
public string Go()
    {
        return "generic Sub called";
    }
}

1 个答案:

答案 0 :(得分:4)

我相信这是因为在编译时不知道一个或多个类型(在这种情况下,TS)时,您将始终收到该错误。

编译器无法保证将使用兼容类型调用doStuff(),因此它会强制您进行强制转换。

要了解编译器无法执行此操作的原因,请尝试按以下方式调用doStuff()

public class X: b {}

...

doStuff<a, X>(); // Compiles ok but:
  

未处理的异常:System.InvalidCastException:无法转换类型为'generic2 1[Demo.Program+X]' to type 'Iab 2 [Demo.Program + X,Demo.Program + Y]'的对象。

因此,您可以使用会导致崩溃的类型来调用它;编译器不会默默地让你这样做。