通用协变和向超类型转换

3

我有一个面向对象的问题,我认为它可以与泛型协变性联系起来。我正在尝试构建一个模块化系统,用于导入不同类型的记录... 该模块包含常见方法,而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);  

如何声明模块以便调用被覆盖的方法?

2个回答

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”进行类型声明是不合法的。
如何声明模块以便我可以调用覆盖的方法?
你必须声明接口遵守协变规则。如何实现由你决定,但首先不要在“输入”位置放置任何“out”参数。

优秀的示例...现在,如何进行重构... :) 谢谢! - Matt Murrell

3

您需要为您的模块使用接口:

public interface IModule<out T> where T : IImportable 
{
  void DoStuff();
  void DoOtherStuff();
}

那么你就可以这样声明你的模块:
IModule<IImportable> = null;

请看此处MSDN文档了解out通用修饰符的详细信息。

Rich - 感谢您的快速回答。我编辑了问题,添加了一些细节到示例中,这可能会改变事情。我似乎无法实现您的更改,因为协变参数T被用作导入方法的输入和从LoadFromTextFile返回的返回值。我是不是完全错了? - Matt Murrell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接