首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型协方差和转换为SuperType

泛型协方差和转换为SuperType
EN

Stack Overflow用户
提问于 2011-12-05 05:37:10
回答 2查看 1K关注 0票数 3

我有一个面向对象的问题,我认为它可以与泛型协方差联系在一起。我正在尝试构建一个模块化系统,用于导入不同类型的记录……模块包含公共方法,而SalesModule包含处理特定逻辑的函数……

代码语言:javascript
复制
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() { ... }; 
}

在另一个函数中:

代码语言:javascript
复制
//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);  

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-05 09:50:10

代码语言:javascript
复制
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不能是输入,因为...好吧,假设这是被允许的,看看会发生什么糟糕的事情:

代码语言:javascript
复制
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.

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

为了防止这种情况,必须将非法的第一步定为非法。带有"out“的类型声明是非法的。

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

您必须声明接口,使其遵守协方差规则。如何做到这一点由你自己决定,但首先不要将任何"out“参数放入"input”位置。

票数 10
EN

Stack Overflow用户

发布于 2011-12-05 05:42:15

你需要为你的模块使用一个接口:

代码语言:javascript
复制
public interface IModule<out T> where T : IImportable 
{
  void DoStuff();
  void DoOtherStuff();
}

然后你就可以像这样声明你的模块:

代码语言:javascript
复制
IModule<IImportable> = null;

有关out通用mdoifier的信息,请参阅here for the MSDN documentation

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8378777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档