通用类型约束似乎没有约束任何东西

时间:2011-06-29 21:10:48

标签: c# .net generics

我在调用泛型方法时遇到了一些问题。在下面的示例中,当我从基类调用ServiceCar时,如果在Dealer中将该方法定义为:

,则会出现错误

定义1:ServiceCar<C>(C carToService) where C : Car<C>

但是当在Dealer中将该方法定义为:

时,我不会在基类中出现错误

定义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;
      }
 }

我的困惑是Microsoft says“其中T:表示类型参数必须是或从指定的基类派生”在定义1的情况下(不编译)C是{{1 }}。那么为什么类型约束参数不能帮助我。我得到的错误是“......无法从Car<C>转换为T”我错过了什么?

4 个答案:

答案 0 :(得分:1)

我认为你是一个令人困惑的不同类型参数。类Car<T>包含参数T,方法ServiceCar<C>包含另一个类型参数C。因此,您需要在方法和类声明中指定两个类型参数:

ServiceCar<C, T>(C carToService) where C : Car<T>

答案 1 :(得分:1)

关闭它看起来像你的混乱的泛型和继承。请记住,其他开发人员在继承您的代码时可能需要做的事情。我总是尽可能选择简单。

public abstract class Car
{
     public bool isServiced;
     public string serviceMessage;

     public abstract string TypeName { get; }
     public virtual void SendToService()
     {
          Dealer.ServiceCar(this);       // error here when Definition 1 used
          servicesMessage = string.Format("Your {0} is clean.", Car.TypeName);
     }
 }

 public class Ford: Car
 {
      public override string TypeName { get { return "Ford"; } }
      //No need to override this because Ford inherits from Car
      //public override void SendToService()
      //{
      //     Dealer.ServiceCar<Ford>(this);
      //     serviceMessage = "Your Ford is clean.";
      //}
 }

 public class Dealer
 {

      public static void ServiceCar(Car carToService)
      {
           carToService.isServiced = true;
      }
 }

答案 2 :(得分:1)

试图打电话时

public static void ServiceCar<C>(C carToService) where C : Car<C> 

用这个

Dealer.ServiceCar<T>(this);

您正在将类型为Car<T>的表达式传递给需要类型为T的表达式的方法。它需要T类型表达式的原因是因为Dealer.ServiceCar<T>明确将C定义为T,因此carToService参数必须是{{1} }}

但是,T无法转换为Car<T>。为什么会这样?它不会从T继承。它继承的唯一东西是T。因此,编译器无法将类型object的表达式转换为类型Car<T>的表达式,如图所示。

要明确的是,您站点的文档和您的类定义指出T必须从T继承,但它没有说明,Car<T>必须从Car<T>继承{ {1}}。

答案 3 :(得分:0)

在定义1中,Dealer.ServiceCar<T>采用T类型的参数。您正在将this传递给方法,该方法的类型为Car<T>。您如何将Car<T>转换为Twhere约束仅表示TCar<T>,但不是相反。