建议43:让接口中的泛型参数支持协变

除了上一建议中提到的使用泛型参数兼容接口不可变性外,还有一种办法是为接口中的泛型声明加上out关键字来支持协变,如下所示:

    interface ISalary<out T>    //使用out关键字
{
void Pay();
}
        static void Main(string[] args)
{
ISalary<Programmer> s = new BaseSalaryCounter<Programmer>();
ISalary<Manager> t = new BaseSalaryCounter<Manager>();
PrintSalary(s);
PrintSalary(t);
} static void PrintSalary(ISalary<Employee> s) //用法正确
{
s.Pay();
}

这段代码在FCL4.0以前是不能编译通过的,因为IEnumerable<T>这个接口在FCL中没有被声明为IEnumerable<out T>:

        static void Main()
{
IList<Programmer> programmers = new List<Programmer>();
IList<Manager> managers = new List<Manager>();
PrintPersonName(programmers);
PrintPersonName(managers);
} static void PrintPersonName(IEnumerable<Employee> persons)
{
foreach (Employee person in persons)
{
Console.WriteLine(person.Name);
}
}

FCL4.0对很多接口进行了修改以支持协变,如IEnumerable<out T>、IEnumerator<out T>、IQuerable<out T>等。由于IEnumerable<out T>现在支持协变,所以上段代码在FCL4.0中能运行得很好。

在我们自己的代码中,如果要编写泛型接口,除非确定该接口中的泛型参数不涉及变体,否则都建议加上out关键字。协变增大了接口的使用范围,而且几乎没有带来什么副作用。

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

最新文章

  1. jQuery实现的简单小功能(实用)
  2. 在ubuntu上建立多svn版本库
  3. AngularJs自定义指令详解(4) - transclude
  4. 谷歌开源项目Google Preview Image Extractor(PIEX) (附上完整demo代码)
  5. (三)C#关于txt文件的读取和写入
  6. Poj 2996 Help Me with the Game
  7. T-SQL实例 函数结果设置为列别名
  8. strtotime 的几点不同
  9. nav标签的作用
  10. Activiti-02-activiti api
  11. Python操作csv文件
  12. PAT乙级-1043. 输出PATest(20)
  13. 你不可不知的Java引用类型【总结篇】
  14. ==,hashcde, equals(一)
  15. 使用generatorConfig配置,自动生成实体类,Mapper接口等
  16. 网络与多线程---OC中多线程使用方法(一)
  17. AngularJS使用angular-formly进行表单验证
  18. 按照用户名和角色查询用户liferay
  19. 深入理解ajax系列第七篇
  20. How far away ?(DFS)

热门文章

  1. mybatis返回Date类型数据 格式化
  2. IaaS vs PaaS vs SaaS
  3. 半导体巨头青睐物联网领域 众强联手打造MCU生态系统
  4. HTTP/HTTPS原理详解
  5. redis的安装和类型及基本命令
  6. protobuff java 包编译(Windows)
  7. AngularJS:Select
  8. spring boot 集成 rabbitmq
  9. 阿里云ECS centos7 支持IPv6
  10. Valid timeZone Values(转)