C# 为什么可以';是否将基引用转换为派生类实现的变量接口?

C# 为什么可以';是否将基引用转换为派生类实现的变量接口?,c#,generics,casting,C#,Generics,Casting,我有以下接口和类: private interface ITest<in T1, out T2> { } private class TestClass { } private class TestClass<T1, T2> : TestClass, ITest<T1, T2> { } 专用接口ITest { } 私有类TestClass { } 私有类TestClass:TestClass,ITest { } 有了这些,我可以做到: Test

我有以下接口和类:

private interface ITest<in T1, out T2>
{
}

private class TestClass
{
}

private class TestClass<T1, T2> : TestClass, ITest<T1, T2>
{
}
专用接口ITest
{
}
私有类TestClass
{
}
私有类TestClass:TestClass,ITest
{
}
有了这些,我可以做到:

    TestClass testBase = new TestClass<Parent, Child> ();

    TestClass<Parent, Child> testGeneric = (TestClass<Parent, Child>)testBase; // Works fine
    ITest<Parent, Parent> testInterface = (ITest<Parent, Parent>)testGeneric; // Works fine
TestClass-testBase=newtestclass();
TestClass testGeneric=(TestClass)testBase;//很好
ITest testInterface=(ITest)testGeneric;//很好
但如果我试图将两者结合起来,我就做不到:

    ITest<Parent, Parent> testInterface = (ITest<Parent, Parent>)testBase; // Fail!
ITest testInterface=(ITest)testBase;//失败!
为什么我不能直接在这里投?这只是C#casting或变体接口的限制吗

如果接口的类型参数与泛型类的类型完全匹配,则它实际上可以工作:

    ITest<Parent, Child> testInterfaceExact = (ITest<Parent, Child>)testBase; // Works
ITest testInterfaceExact=(ITest)testBase;//作品

问题在于
TestClass
实际上不是
ITest
。它与接口无关,因此您不能只写:

(ITest<T1, T2>)new TestClass();
Downcast在运行时可能成功,也可能失败,这取决于实际对象是否为派生类型。这将永远成功

现在,如果您想要对派生对象进行基准引用,这很好。但是,如果您希望将其转换为仅为派生类所知的任何内容,例如您的接口,则必须首先执行向下转换:

TestClass derived = new TestClass<T1, T2>();
ITest<T1, T2> interf = (TestClass<T1, T2>)derived;
TestClass-derived=newtestclass();
ITest interf=(TestClass)派生;
您甚至不必强制转换到接口,因为泛型类已经实现了该接口

变量类型参数的问题越来越严重。如果编译器无法访问泛型参数的方差信息,则无法检查强制转换是否可行。一旦您强制转换到泛型类,编译器将能够正确推断方差并分配引用:

TestClass derived = new TestClass<Parent, Child>();
ITest<Parent, Parent> interf = (TestClass<Parent, Child>)derived;
TestClass-derived=newtestclass();
ITest interf=(TestClass)派生;
事实上,您的最后一行是有效的,即:

ITest<Parent, Child> testInterfaceExact = (ITest<Parent, Child>)testBase;
ITest testInterfaceExact=(ITest)testBase;

这仅仅是因为您没有更改泛型类型,所以编译器不必在这一行推断方差信息(它没有)。

无法复制,在这里和这里都可以正常工作。请提供一个示例并说明您正在使用的编译器版本。我希望它能正常工作,
Child
实际上是
Parent
的子类型吗?
ITest<Parent, Child> testInterfaceExact = (ITest<Parent, Child>)testBase;