Como Grzenio señala correctamente, una expresión de tipo T no se puede convertir en TwoType. El compilador no sabe que se garantiza que la expresión sea de tipo TwoType, eso está garantizado por su declaración "if", pero el compilador no tiene en cuenta la implicación de la sentencia if al analizar tipos.Más bien, el compilador supone que T puede ser de cualquier tipo que satisfaga la restricción, incluido ThreeType, un tipo derivado de OneType pero no TwoType. Obviamente no hay conversión de ThreeType a TwoType, por lo que tampoco hay conversión de T a TwoType.
Puede engañar al compilador para que lo permita diciendo "bueno, trate la T como objeto y luego convierta el objeto a TwoType". Cada paso en el camino es legal: T es convertible a objeto, y puede haber una conversión de objeto a TwoType, por lo que el compilador lo permite.
A continuación, obtendrá el mismo problema al convertir de SubClass a MyClass<T>
. De nuevo, puedes resolver el problema lanzando al objeto primero.
Sin embargo, este código sigue siendo incorrecto:
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
}
}
Por qué está mal? Bueno, considera todo lo que podría salir mal aquí. Por ejemplo: usted dice
class AnotherTwoType : TwoType { }
...
x = Factory<TwoType>(new AnotherTwoType());
¿Qué ocurre? No llamamos al constructor SubClass porque el argumento no es exactamente del tipo TwoType, es de un tipo derivado de TwoType. En lugar de un interruptor, es probable que desee
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
}
Esto sigue siendo incorrecto. De nuevo, piense en lo que podría ir mal:
x = Factory<OneType>(new TwoType());
¿Qué pasa ahora? el argumento es TwoType, creamos una nueva SubClass y luego intentamos convertirla a MyClass<OneType>
, pero no hay conversión de SubClass a MyClass<OneType>
, por lo que se bloqueará y morirá en el tiempo de ejecución.
El código correcto para su fábrica es
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
}
es que ahora todo claro? Puede considerar un enfoque diferente por completo; cuando necesite tantos lanzamientos y verificaciones de tipo de tiempo de ejecución para convencer al compilador de que el código es correcto, eso es evidencia de que todo es un mal olor de código.
¿Qué error devuelve el compilador? – TJMonk15
Preguntas modificadas – Graviton