【问题标题】:Generic Type Constraint does not seem to be constraining anything通用类型约束似乎没有约束任何东西
【发布时间】:2013-11-09 21:35:31
【问题描述】:

我在调用泛型方法时遇到了一些问题。在下面的示例中,当我从基类调用 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 是 Car&lt;C&gt;。那么为什么类型约束参数不能帮助我。我收到的错误是“...无法从 Car&lt;T&gt; 转换为 T”我错过了什么?

【问题讨论】:

    标签: c# .net generics


    【解决方案1】:

    尝试调用时

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

    有了这个

    Dealer.ServiceCar<T>(this);
    

    您将Car&lt;T&gt; 类型的表达式传递给需要T 类型表达式的方法。它需要T 类型的表达式的原因是因为Dealer.ServiceCar&lt;T&gt;C 显式定义为T,因此carToService 参数必须是T

    但是,Car&lt;T&gt; 不能转换为 T。为什么应该这样?它不继承自T。它唯一继承的东西是object。因此,编译器无法将Car&lt;T&gt; 类型的表达式转换为T 类型的表达式,正如所示。

    需要明确的是,您站点的文档和您的类定义声明 T 必须从 Car&lt;T&gt; 继承,但没有说相反,Car&lt;T&gt; 必须从 T 继承。

    【讨论】:

      【解决方案2】:

      我觉得你混淆了不同类型的参数。类Car&lt;T&gt; 有参数T 和方法ServiceCar&lt;C&gt;另一个 类型参数C。所以需要在方法和类声明中同时指定类型参数:

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 我知道这不是一个理想的样本,并且有更好的方法来做到这一点。我只是想找到一种从基类和继承类中调用相同泛型方法的方法。
        • 哦,好的。你可以试试这个然后public static void ServiceCar&lt;C&gt;(C carToService) where C : Car 并从你的基类中删除泛型定义。
        【解决方案4】:

        在定义 1 中,Dealer.ServiceCar&lt;T&gt; 采用 T 类型的参数。您正在将this 传递给类型为Car&lt;T&gt; 的方法。你将如何将Car&lt;T&gt; 转换为Twhere 约束只说 TCar&lt;T&gt;,但不是相反。

        【讨论】:

          猜你喜欢
          • 2010-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多