简化协方差和逆变实现

时间:2012-07-02 13:06:25

标签: c#-4.0 covariance contravariance

实现独立的调度程序类我必须进入以下界面:

public interface ISchedulableContext<in T1, out T2> where T1: T2, ISchedulerConfigProvider
{
    void LogMessage(LoggingEventLevel level, string eventName, string Message);
    void Process(ISchedulerConfigProvider schedulerConfig);
    IEnumerable<T2> GetSchedulerConfig();
    void SaveUpdatedConfig(IEnumerable<T1> schedulers);
}

它可以工作,但需要明确和冗余的指定和传递类型ISchedulableContext&lt; ISchedulerConfigProvider,ISchedulerConfigProvider&gt;

public class SchedulableCore: ISchedulableContext<ISchedulerConfigProvider,ISchedulerConfigProvider>
{ 
...
}

public class TaskScheduler
{
    private ISchedulableContext<ISchedulerConfigProvider, ISchedulerConfigProvider> core;

    public TaskScheduler(ISchedulableContext<ISchedulerConfigProvider, ISchedulerConfigProvider> core)
    {
        this.core = core;
    }
}

我想简化这种实现并使用简单的接口实现:

public class SchedulableCore: ISchedulableContext
{ 
    /*...*/
    public IEnumerable<ISchedulerConfigProvider> GetSchedulerConfig()
    {
        return (IEnumerable<ISchedulerConfigProvider>)/*...*/;
    }

    public void SaveUpdatedConfig(IEnumerable<ISchedulerConfigProvider> schedulers)
    { /*...*/ }
}

是否可以简化?

1 个答案:

答案 0 :(得分:1)

由于您使用接口作为类型参数,因此您可以使用接口本身而不是类型参数:

public interface ISchedulableContext {
  void LogMessage(LoggingEventLevel level, string eventName, string Message);
  void Process(ISchedulerConfigProvider schedulerConfig);
  IEnumerable<ISchedulerConfigProvider> GetSchedulerConfig();
  void SaveUpdatedConfig(IEnumerable<ISchedulerConfigProvider> schedulers);
}

请注意,这与您发布的内容不同。在您的示例中,T2可能与ISchedulerConfigProvider不同,但T1必须遵守它。此外,Process方法不使用任何类型参数(看起来应该如此)。我并不完全清楚为什么会这样。如果这是故意的,也许你可以提供一些解释。

另一种选择是只提供一个不变类型参数:

public interface ISchedulableContext<T> where T : ISchedulerConfigProvider {
  void LogMessage(LoggingEventLevel level, string eventName, string Message);
  void Process(T schedulerConfig);
  IEnumerable<T> GetSchedulerConfig();
  void SaveUpdatedConfig(IEnumerable<T> schedulers);
}

另一个选择是将界面分为两个:一个用于T上的协变方法,另一个用于逆变方法。