与C#Generics的协方差

 兄弟465748208_279 发布于 2023-01-08 17:14

给定接口IQuestion和该接口的实现AMQuestion,假设以下示例:

List typed = new List();
IList nonTyped = typed;

正如预期的那样,这个例子产生一个编译错误,说明两者的类型不同.但它表明存在明确的转换.所以我把它改成这样:

List typed = new List();
IList nonTyped = typed as IList;

然后编译,但在运行时,nonTyped始终为空.如果有人可以解释两件事:

为什么这不起作用.

我怎样才能达到预期的效果.

这将不胜感激.谢谢!

3 个回答
  • 为什么它不工作:as返回null如果值的动态类型不能被强制转换为目标类型,并且List<AMQuestion>不能被强制转换为IList<IQuestion>.

    但为什么不能呢?好吧,检查一下:

    List<AMQuestion> typed = new List<AMQuestion>();
    IList<IQuestion> nonTyped = typed as IList<IQuestion>;
    nonTyped.Add(new OTQuestion());
    AMQuestion whaaaat = typed[0];
    

    IList<IQuestion>说"你可以添加任何IQuestion给我".但这是一个它无法保留的承诺,如果它是一个List<AMQuestion>.

    现在,如果您不想添加任何内容,只需将其视为IQuestion兼容事物的集合,那么最好的办法就是将其转换为IReadOnlyList<IQuestion>with List.AsReadOnly.由于只读列表不能添加奇怪的内容,因此可以正确地进行转换.

    2023-01-08 17:16 回答
  • 这样的事实AMQuestion实现了IQuestion接口并没有转化为List<AMQuestion>从派生List<IQuestion>.

    因为此演员表是非法的,您的as运营商会返回null.

    您必须单独投射每个项目:

    IList<IQuestion> nonTyped = typed.Cast<IQuestion>().ToList();
    

    关于您的评论,请考虑以下代码,以及常见的陈词滥调动物示例:

    //Lizard and Donkey inherit from Animal
    List<Lizard> lizards = new List<Lizard> { new Lizard() };
    List<Donkey> donkeys = new List<Donkey> { new Donkey() };
    
    List<Animal> animals = lizards as List<Animal>; //let's pretend this doesn't return null
    animals.Add(new Donkey()); //Reality unravels!
    

    如果我们被允许转换List<Lizard>为a List<Animal>,那么我们理论上可以Donkey在该列表中添加一个新的,这将破坏继承.

    2023-01-08 17:16 回答
  • 问题是List<AMQuestion>无法强制转换IList<IQuestion>,因此使用as运算符无济于事.在这种情况下显式转换意味着转换AMQuestionIQuestion:

    IList<IQuestion> nonTyped = typed.Cast<IQuestion>.ToList();
    

    顺便说一句,你的标题中有"协方差"一词.在IList类型协变.这正是演员阵容不存在的原因.原因是IList界面具有T一些参数一些返回值,因此既in不能out也不能使用T.(@Sneftel有一个很好的例子来说明为什么不允许这种演员表.)

    如果您只需要从列表中读取,则可以使用IEnumerable:

    IEnumerable<IQuestion> = typed;
    

    这将起作用,因为IEnumerable<out T>out定义,因为您无法将其T作为参数传递.您通常应该在代码中使最弱的"承诺"保持可扩展性.

    2023-01-08 17:18 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有