zoukankan      html  css  js  c++  java
  • C#笔记16:协变与逆变

    C#笔记16:协变与逆变

    本章概要:
    1:协变与逆变概念
    2:协变
    3:逆变
    4:注意事项
    5:接口变体语法

    1:逆变与协变概念
        “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
        “逆变”则是指能够使用派生程度更小的类型。
         如果泛型接口或委托的泛型参数声明为协变或逆变,则将该泛型接口或委托称为“变体”。

    2:协变
         查看下面代码:

    IEnumerable<String> strings = new List<String>(); 
    IEnumerable<Object> objects = strings;

         在 .NET Framework 早期版本中,在 Option Strict On 条件下,此代码会导致 C# 和 Visual Basic 中出现编译错误。但是现在,您可以使用 strings 代替 objects,如上例所示,因为 IEnumerable<(Of <(T>)>) 接口为协变接口。

    3:逆变
         逆变允许方法具有与接口的泛型形参所指定的实参类型相比,派生程度更小的实参类型。为展示逆变功能,假设您已创建 BaseComparer 类来比较 BaseClass 类的实例。BaseComparer 类实现 IEqualityComparer<BaseClass>(在 Visual Basic 中为 IEqualityComparer(Of BaseClass))接口。因为 IEqualityComparer<(Of <(T>)>) 接口现在为逆变接口,所以您可以使用 BaseComparer 来比较继承 BaseClass 类的类的实例。以下代码示例中演示了这一点。

    // Simple hierarchy of classes.
    class BaseClass { }
    class DerivedClass : BaseClass { }
    
    // Comparer class.
    class BaseComparer : IEqualityComparer<BaseClass> 
    {
        public int GetHashCode(BaseClass baseInstance)
        {
            return baseInstance.GetHashCode();
        }
        public bool Equals(BaseClass x, BaseClass y)
        {
            return x == y;
        }
    }
    class Program
    {
        static void Test()
        {
            IEqualityComparer<BaseClass> baseComparer = new BaseComparer();
    
            // Implicit conversion of IEqualityComparer<BaseClass> to 
            // IEqualityComparer<DerivedClass>.
            IEqualityComparer<DerivedClass> childComparer = baseComparer;
        }
    }

    4:注意事项

        有引用类型才支持使用泛型接口中的变体。值类型不支持变体。 实现变体接口的类仍是固定类。例如,虽然 List<(Of <(T>)>) 实现协变接口 IEnumerable<(Of <(T>)>),但无法将 List<string>.

    // The following line generates a compiler error
    // because classes are invariant.
    // List<Object> list = new List<String>();
    
    // You can use the interface object instead.
    IEnumerable<Object> listObjects = new List<String>();

    5:接口变体语法
         若要声明变体泛型接口,可以对泛型类型参数使用 in 和 out 关键字。
         您可以使用 out 关键字,将泛型类型参数声明为协变。
         您可以使用 in 关键字,将泛型类型参数声明为逆变。

    NET C# 入门级 .NET C# 专业级 .NET 架构级 BS系统专业级 BS系统安全
    1.开篇及C#程序、解决方案的结构
    2.源码管理之TFS入门
    3.打老鼠初级
    ……
    21.CMS之主要功能实现
    22.进程和线程基础
    23.类型转换
    24.算法基础
    25.初级课程之剩余知识点
    1.消灭打老鼠游戏中的自定义委托
    2.垃圾回收
    3.Dispose模式
    ……
    16.异常使用指导
    17.最常用的重构指导
    18.Debug和IDE的进阶
    19.Resharper的使用
    20.ILSPY的使用
    1.Socket入门
    2.打造打老鼠游戏网络版
    3.WCF入门
    ……
    10.依赖注入
    11.万物兼可测试
    12.软件指标之覆盖率计算
    13.软件指标之代码行
    14.软件指标之圈复杂度、嵌套深度
    1.HTML
    2.WebForm原理
    3.CSS必知必会
    ……
    19.让浏览器缓存Shop
    20.Asp.net的生命周期
    21.Asp.net网站的发布以及调试晋级
    22.BS程序的本质
    23.压力测试我们的Shop
    1.Fiddler必知必会
    2.IE开发者工具必知必会
    3.跨站脚本防范
    4.权限欺骗防范
    5.参数越界防范
    6.会话劫持防范
    7.CSRF防范
    8.盗链防范
    9.静态文件的保护


     
     
    Creative Commons License本文基于Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
  • 相关阅读:
    Java日期时间差以及获取几天后或几天前
    java数组扩增的三种方式
    折半查找、冒泡排序和选择排序
    JavaSE-Map的三种循环
    Chrome浏览器showModalDialog兼容性及解决方案
    Integeter127与128
    statis代码块以及非static代码块之执行
    return、break、continue区别以及作用范围
    nodeJs + vue.js 小案例
    cordova CLI 命令
  • 原文地址:https://www.cnblogs.com/luminji/p/1824487.html
Copyright © 2011-2022 走看看