我有一个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() { ... };
}
并在另一个函数中:
//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);
如何声明模块以便我可以调用重写的方法?
答案 0 :(得分:10)
public interface IModule<out T> where T : IImportable
{
void Import(IEnumerable<T> list); // Error Occurs here...
IEnumerable<T> LoadFromTextFile(TextReader sr);
}
错误是正确的。我们选择“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.
您刚刚将一个老虎列表导入到一个只知道如何处理长颈鹿的模块中。
为了防止这种情况,必须使非法步骤成为第一个步骤。使用“out”类型声明是非法的。
如何声明模块以便我可以调用重写的方法?
您必须声明接口以使其遵守协方差规则。你如何做到这一点取决于你,但首先不要将任何“出”参数放入“输入”位置。
答案 1 :(得分:3)
您需要为模块使用接口:
public interface IModule<out T> where T : IImportable
{
void DoStuff();
void DoOtherStuff();
}
然后你就可以像这样声明你的模块:
IModule<IImportable> = null;
请参阅here for the MSDN documentation了解out
通用mdoifier。