I have a simple factory method which provides a concrete implementation instance based on a generic type parameter provided. If the concrete classes inherit from a common abstract base class with a type parameter I cannot cast them. The compiler tells me Error 2 Cannot convert type 'Car' to 'VehicleBase<T>'
. It works fine if I substitute the abstract class for an interface with the same type parameter, or if I remove the generic type parameter from the abstract class.
interface IWheel
{
}
class CarWheel : IWheel
{
}
abstract class VehicleBase<T>
{
}
class Car : VehicleBase<CarWheel>
{
}
class VehicleFactory
{
public static VehicleBase<T> GetNew<T>()
{
if (typeof(T) == typeof(CarWheel))
{
return (VehicleBase<T>)new Car();
}
else
{
throw new NotSupportedException();
}
}
}
This fails to compile on (VehicleBase<T>)new Car()
. Is this a compiler defect, or could this be a deliberate design decision to treat abstract classes and interfaces with type parameters differently?
As a workaround I can always make the abstract class implement an interface and use this as the return value for my factory method, but I'd still like to know why this behavior is happening.
That is not provable, because generic code needs to work (with the same IL) for every possible T
, and there is nothing to say that Car : VehicleBase<float>
, for example. The compiler does not over-analyse the fact that the if
check sows that T
is CarWheel
- the static checker treats each statement separately, it doesn't try to understand the cause-and-effect of conditions.
To force it, cast to object
in the middle:
return (VehicleBase<T>)(object)new Car();
However! Your approach isn't really "generic" as such.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With