通用协方差和转换为SuperType

Mat*_*ell 3 c# generics

我有一个OO问题,我认为可以与Generic Covariance联系起来.我想建立一个模块化系统导入不同类型的记录...模块包含了常用的方法,以及SalesModule包含用于处理特定的逻辑功能...

public interface IImportable { ... void BuildSqlDataRecord(); ...  }
public class Sales : IImportable { ... }
public interface IModule<out T> where T : IImportable
{
    void Import(IEnumerable<T> list);  // Error Occurs here...
    IEnumerable<T> LoadFromTextFile(TextReader sr);
}
public abstract class Module<T> : IModule<T> where T : IImportable
{ 
    public void Import(IEnumerable<T> list) { ... T.BuildSqlDataRecord(); ... } 
    public IEnumerable<T> LoadFromTextFile(TextReader sr) { ... }
}
public class SalesModule : Module<Sales>
{
    public override void BuildSqlDataRecord() { ... }; 
}
Run Code Online (Sandbox Code Playgroud)

在另一个功能:

//Module<IImportable> module = null;
IModule<IImportable> module = null;
if(file.Name == "SALES")
    module = new SalesModule();
else
    module = new InventoryModule();

var list = module.LoadFromTextFile(sr);
module.Import(list);  
Run Code Online (Sandbox Code Playgroud)

如何声明模块以便我可以调用重写的方法?

Eri*_*ert 10

public interface IModule<out T> where T : IImportable
{
    void Import(IEnumerable<T> list);  // Error Occurs here...
    IEnumerable<T> LoadFromTextFile(TextReader sr);
}
Run Code Online (Sandbox Code Playgroud)

错误是正确的.我们选择"out"作为表示协方差的关键字,提醒您T只能出现在"输出"位置.在突出显示的行中,T显示为输入.

T不能是输入,因为......好吧,假设它被允许并看到发生了什么坏事:

IModule<Giraffe> gm = GetMeAModuleOfGiraffes();
IModule<Animal> am = gm; // Legal because of covariance.
IEnumerable<Tiger> tigers = GetMeASequenceOfTigers();
IEnumerable<Animal> animals = tigers; // Legal because of covariance.
am.Import(animals); // Uh oh.
Run Code Online (Sandbox Code Playgroud)

您刚刚将一个老虎列表导入到只知道如何处理长颈鹿的模块中.

为了防止这种情况,必须使非法步骤是第一个.类型声明是非法的"out".

如何声明模块以便我可以调用重写的方法?

您必须声明接口以使其遵守协方差规则.你如何做到这一点取决于你,但首先不要将任何"out"参数放入"输入"位置.