正如 Grzenio 正确指出的那样,类型 T 的表达式不能转换为 TwoType。编译器不知道表达式保证是 TwoType 类型——这是由您的“if”语句保证的,但编译器在分析类型时不考虑 if 语句的含义。相反,编译器假定 T 可以是任何满足约束的类型,包括 ThreeType,一种派生自 OneType 但不是 TwoType 的类型。显然没有从 ThreeType 到 TwoType 的转换,所以也没有从 T 到 TwoType 的转换。
您可以通过说“好吧,将 T 视为对象,然后将对象转换为 TwoType”来欺骗编译器允许它。沿途的每一步都是合法的——T 可以转换为对象,并且可能存在从对象到 TwoType 的转换,因此编译器允许这样做。
然后,您将遇到从 SubClass 转换为 MyClass<T> 的相同问题。同样,您可以通过先转换为对象来解决问题。
但是,这段代码仍然是错误的:
public static MyClass<T> Factory<T>(T vd)
where T:OneType
{
switch(vd.TypeName)
{
case Constant.TwoType
// WRONG
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}
}
为什么错了?好吧,考虑一下这里可能出错的一切。例如:你说
class AnotherTwoType : TwoType { }
...
x = Factory<TwoType>(new AnotherTwoType());
会发生什么?我们不调用 SubClass 构造函数,因为参数不完全属于 TwoType 类型,它是从 TwoType 派生的类型。而不是开关,你可能想要
public static MyClass<T> Factory<T>(T vd)
where T:OneType
{
if (vd is TwoType)
// STILL WRONG
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}
这仍然是错误的。再次,想想可能出了什么问题:
x = Factory<OneType>(new TwoType());
现在会发生什么?参数是TwoType,我们新建一个SubClass,然后尝试将其转换为MyClass<OneType>,但是没有从SubClass转换为MyClass<OneType>,所以这会在运行时崩溃死。
您工厂的正确代码是
public static MyClass<T> Factory<T>(T vd)
where T:OneType
{
if (vd is TwoType && typeof(T) == typeof(TwoType))
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}
现在一切都清楚了吗?您可能会考虑完全不同的方法; 当您需要如此多的强制转换和运行时类型检查来让编译器相信代码是正确的时,这就是整个事情都是糟糕的代码味道的证据。