I am having some issues surrounding the calling of a generic method. In the example below, when I call ServiceCar from the base class I get an error when that method is defined in Dealer as:
Definition 1: ServiceCar<C>(C carToService) where C : Car<C>.
But I do not get an error in the base Class when that method is defined in Dealer as:
Definition 2: ServiceCar<C>(Car<C> carToService) where C : Car<C>
public abstract class Car<T> where T: Car<T>
{
public bool isServiced;
public string serviceMessage;
public virtual void SendToService()
{
Dealer.ServiceCar<T>(this); // error here when Definition 1 used
serviceMessage = "Your car is clean.";
}
}
public class Ford: Car<Ford>
{
public override void SendToService()
{
Dealer.ServiceCar<Ford>(this);
serviceMessage = "Your Ford is clean.";
}
}
public class Dealer
{
// When the parameter is defined as C (as commented below) an error occurs
// When the parameter is defined as Car<C> there are no errors
// public static void ServiceCar<C>(C carToService) where C : Car<C>
public static void ServiceCar<C>(Car<C> carToService) where C : Car<C>
{
carToService.isServiced = true;
}
}
My confusion is that Microsoft says that “where T: means the type argument must be or derive from the specified base class” Well in the case of definition 1 (which does not compile) C is Car<C>. So why isn’t the type constraint parameter helping me out. The error I am getting reads “…cannot convert from Car<T> to T” What am I missing?
When attempting to call
with this
you are passing an expression of type
Car<T>to a method that wants an expression of typeT. The reason it wants an expression of typeTis becauseDealer.ServiceCar<T>is explicitly defining theCasT, so thecarToServiceparameter must be aT.However,
Car<T>is not convertable toT. Why should it be? It does not inherit fromT. The only thing it inherits from isobject. Therefore, the compiler cannot convert an expression of typeCar<T>to an expression of typeT, just as indicated.To be clear, the documentation that you site and your class definition states that
Tmust inherit fromCar<T>, but it does not say the inverse, thatCar<T>must inherit fromT.