zoukankan      html  css  js  c++  java
  • c#4.0泛型接口和泛型委托的协变和逆变

    先看个例子,此代码在c# 4.0下可以编译通过,因为c#4.0才开始支持逆变和协变

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConsoleApplication1
    {
     
        
    class Program
        {
            
    public static void Main()
            {

                IEnumerable
    <object> objs = new List<string>(); //协变

                Action
    <object> action1 = o => { };

                Action
    <string> action2 = action1;//逆变
            }
        }
    }

    下面是泛型接口IEnumerable<T>相关类型的定义

       

    代码
     public interface IEnumerable<out T> : IEnumerable
        {
            
    // Summary:
            
    //     Returns an enumerator that iterates through the collection.
            
    //
            
    // Returns:
            
    //     A System.Collections.Generic.IEnumerator<T> that can be used to iterate through
            
    //     the collection.
            IEnumerator<T> GetEnumerator();
        }

        
    public interface IEnumerator<out T> : IDisposable, IEnumerator
        {
            
    // Summary:
            
    //     Gets the element in the collection at the current position of the enumerator.
            
    //
            
    // Returns:
            
    //     The element in the collection at the current position of the enumerator.
            T Current { get; }
        }

    可以看到T在IEnumerable定义中比以前多了out的修饰符。out表示T在泛型类型中只能被用作输出。也就是说T定义的对象是只会被用作赋值给客户代码中的引用。这样凡是使用IEnumerable<BaseType>类型的地方都可以被安全的替换成IEnumerable<SubType>.因为子类型(SubType)可以安全替换父类型(BaseType)

    下面是泛型委托Action<T>的定义

       public delegate void Action<in T>(T obj);

    这里是用in修饰T。说明T在泛型中只会被用作输入,也就是说T定义的引用只能用作接受客户代码的赋值。所以使用Action<SubType>的地方都可以被安全的替换成Acton<BaseType>.道理和上面一样子类型(SubType)可以安全替换父类型(BaseType)。

    总结:协变和逆变允许我们定义的泛型接口和泛型委托能更加的通用。而且保证不会破坏类型安全。

  • 相关阅读:
    STM32的GPIO工作原理 | 附电路图详细分析
    话说上拉电阻和下拉电阻
    Linux下MySQL数据库常用基本操作
    Linux acpi off学习的必要
    CentOS 6.2出现Disk sda contains BIOS RAID metadata解决方法
    降低开关电源纹波的三个要素
    什么是RFID? 射频识别技术的特点及工作原理!
    亲测可用的国内maven镜像
    Linux 删除文件夹和文件的命令
    [Gradle] 在 Eclipse 下利用 gradle 构建系统
  • 原文地址:https://www.cnblogs.com/xhan/p/1748943.html
Copyright © 2011-2022 走看看