创建从基础 class 派生的 classes 的列表 - 没有给定的参数对应于所需的形式参数

Create list of classes derived from a base class - There is no argument given that corresponds to the required formal parameter

我正在创建 Strategy<Option> 的以下列表:

List<Runner<Strategy<Options>>> runners = new List<Runner<Strategy<Options>>> {
  new Runner<MonthlyStrategy>(new MonthlyStrategy(x => { x.Window = 2000; }))
}; 

我将添加源自 Strategy<Options> 的策略,但出现错误:

There is no argument given that corresponds to the required formal parameter 'strategy' of 'Runner<MonthlyStrategy>.Runner(string, MonthlyStrategy)'
The type 'MonthlyStrategy' cannot be used as type parameter 'T' in the generic type or method 'Runner<T>'. There is no implicit reference conversion from 'MonthlyStrategy' to 'Strategy<Options>'

我的代码如下:

public class Options { }

public interface IStrategy<T> where T: Options {
  T Options { get; }
}

public abstract class Strategy<T> : IStrategy<T> where T : Options {
  public abstract T Options { get; }
  public Strategy(Action<T> options) {
    options(Options);
  }
}

public class Runner<T> where T : Strategy<Options> {
  public T Strategy { get; } 
  public Runner(String cron, T strategy) {  
    Strategy = strategy;
  } 
} 

public class MontlhyStrategyOptions : Options { 
  public Int32 Window { get; set; }= 10; 
} 

public class MonthlyStrategy : Strategy<MontlhyStrategyOptions> {

  public override MontlhyStrategyOptions Options => new MontlhyStrategyOptions();

  public MonthlyStrategy(Action<MontlhyStrategyOptions> options) : base (options) { }

}

如何解决?

C# 不支持 variance for classes (i.e. in general case Strategy<MontlhyStrategyOptions> is not Strategy<Options> - explanation with lists). To achieve something like this you can try migrating to covariant 接口:

public interface IStrategy<out T> where T: Options {
    T Options { get; }
}

public abstract class Strategy<T> : IStrategy<T> where T : Options {
    public abstract T Options { get; }
    public Strategy(Action<T> options) {
        options(Options);
    }
}

public interface IRunner<out T> where T : IStrategy<Options> {}

public class Runner<T> : IRunner<T> where T : IStrategy<Options>
{
    public T Strategy { get; }

    public Runner(String cron, T strategy)
    {
        Strategy = strategy;
    }
}

public class MontlhyStrategyOptions : Options { 
    public Int32 Window { get; set; }= 10; 
}

public class MonthlyStrategy : Strategy<MontlhyStrategyOptions>
{
    public override MontlhyStrategyOptions Options => new MontlhyStrategyOptions();
    public MonthlyStrategy(Action<MontlhyStrategyOptions> options) : base(options)
    {
    }
}

和用法:

List<IRunner<IStrategy<Options>>> runners = new List<IRunner<IStrategy<Options>>> {
    new Runner<MonthlyStrategy>("", new MonthlyStrategy(x => { x.Window = 2000; }))
};