我可以在泛型类中创建一个泛型对象,其中要创建的对象的类对泛型类型参数有约束吗?

时间:2012-01-08 19:22:44

标签: c# generics interface type-constraints

我有一个通用界面,

   public interface ICalculator<in T>
   {
      void Calculate(T input);
   }

通用计算器,

   public class GeneralCalculator<T> : ICalculator<T>
   {
      public void Calculate(T input)
      {
         bla bla
      }
   }

仅适用于某些类型的特定计算器,

   public class SpecificAndFastCalculator<T> : ICalculator<T> where T : ISpecificInterface
   {
      public void Calculate(T input)
      {
         bla bla
      }
   }

和装饰ICalculators的装饰者:

   public class CalculatorDecorator<T> : ICalculator<T>
   {
      private readonly ICalculator<T> component;

      public CalculatorDecorator()
      {  
         component = (typeof (ISpecificInterface).IsAssignableFrom(typeof (T)))
                        ? new SpecificAndFastCalculator<T>() //Compiler Error 
                        : new GeneralCalculator<T>();
      }

      public void Calculate(T input)
      {
         component.Calculate(input); bla bla
      }
   }

问题是,如您所见,编译器不接受调用 SpecificAndFastCalculator 的构造函数,因为它不知道 T 是否服从约束 T:ISpecificInterface 即使我在运行时检查它。编译器可以是正确的,还是仅仅因为它不够智能而拒绝代码?

有没有办法将组件字段分配给 SpecificAndFastCalculator

据我所见,我有以下选择:

  • SpecificAndFastCalculator 编写特定的装饰器 组件,我认为胜过装饰者的目的,
  • 以某种方式使用反射魔法(我不知道如何)
  • 删除 T:ISpecificInterface 约束,记录并希望 为了最好。

还有其他方法吗?暂时我选择了第三个选项(删除约束),你会建议什么?

2 个答案:

答案 0 :(得分:2)

如果您更改CalculatorDecorator<T>的构造函数,它应该可以工作:

public CalculatorDecorator()
{  
    component = (ICalculator<T>)(typeof (ISpecificInterface).IsAssignableFrom(typeof (T))
        ? typeof(SpecificAndFastCalculator<>)
            .MakeGenericType(typeof(T))
            .GetConstructor(new Type[0])
            .Invoke(null)
        : new GeneralCalculator<T>());
}

这将使用专门的实现,并仍然确保所有其他地方创建的实例也将使用它。

答案 1 :(得分:0)

您应该能够在没有通用约束的情况下定义SpecificAndFastCalculator,因为在运行时您可以保证它符合ISpecificInterface。

当然,您需要将SpecificAndFastCalculator运行时转换为ICalculator<T>SpecificAndFastCalculator必须已为给定的T实现ICalculator<T>

例如,如果T == Int32,并且您已将SpecificAndFastInt32Calculator定义为:

public class SpecificAndFastInt32Calculator : ICalculator<Int32> { ... }

将此实例转换为ICalculator将在运行时编译和工作。