5

不要认为标题可以解释我在说什么,而且解释起来有点困难,所以我让代码来说话。您可以将其复制+粘贴到 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";
    }
}
4

1 回答 1

4

TS我相信这是因为当编译时不知道一种或多种类型(在本例中为 )时,您总是会收到该错误。

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

要查看编​​译器为什么不能这样做,请尝试doStuff()如下调用:

public class X: b {}

...

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

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

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

于 2013-05-27T08:06:01.547 回答