泛型构造要求类型“IConditionalOperator”具有公共默认构造函数

问题描述

我想创建一个应该实现通用单元测试的类型层次结构,使用抽象类型作为测试夹具。相同的模式在 C# 中运行良好,但我面临编译器错误:“泛型构造要求类型‘IConditionalOperator’具有公共认构造函数。”:

   type Color =
      | White = 0xFFFFFF
      | Silver = 0xC0C0C0
      | Gray = 0x808080

   type IConditionalOperator =
      abstract member GetName : Color -> string

   type PatternMatching() =
      interface IConditionalOperator with
         member this.GetName color =
               match color with
               | Color.White -> "White"
               | Color.Silver -> "Silver"
               | Color.Gray -> "Gray"
               | _ -> "None"

   [<AbstractClass>]
   type ConditionalOperatorTest<'T when 'T :> IConditionalOperator and 'T : (new : unit -> 'T)>() =
      member this.ConditionalOperator_ReturnsName(name: string) = None

   type PatternMatchingtest() =
      inherit ConditionalOperatorTest<IConditionalOperator>()

相应的 C# 代码有效,如下所示:

   public enum Color
   {
      White = 0xFFFFFF,Silver = 0xC0C0C0,Gray = 0x808080,}

   public interface IConditionalOperator
   {
      string GetName(Color color);
   }

   public class IfStatement : IConditionalOperator
   {
      public string GetName(Color color)
      {
         if (color == Color.White)
         {
            return "White";
         }
         else if (color == Color.Silver)
         {
            return "Silver";
         }
         else if (color == Color.Gray)
         {
               return "Gray";
         }
         else
         {
            return "None";
         }
      }
   }

   public abstract class ConditionalOperatorTest<T> where T : IConditionalOperator,new()
   {
      public void ConditionalOperator_ReturnsName(Color color,string name) {}
   }

   public class IfStatementTest : ConditionalOperatorTest<IfStatement> {}

解决方法

您已定义 ConditionalOperatorTest<'T> 以便它要求 'T 具有默认构造函数,这意味着 'T 不能是接口。因此,不要将 IConditionalOperator 指定为 'T,而是使用具体的 PatternMatching 类型:

type PatternMatchingTest() =
    inherit ConditionalOperatorTest<PatternMatching>()

进行此更改后,F# 版本现在与原始 C# 代码匹配:ConditionalOperatorTest<IfStatement>