图文详解C#中的协变与逆变

图文详解C#中的协变与逆变

什么是协变与逆变

协变和逆变是指可以使用派生类型来代替基类型的能力。协变用于返回值类型,逆变用于参数类型。在C#中,协变和逆变可以应用于委托(delegate)和泛型(generic)类型。

协变

协变可用于返回类型,指一个方法返回类型可以使用它继承的类型。使用out关键字可实现协变。

示例1

class Program
{
    static void Main(string[] args)
    {
        IAnimalContainer<Cat> catContainer = new AnimalContainer<Cat>();
        IAnimalContainer<Animal> animalContainer = catContainer;
        Console.WriteLine(animalContainer.GetType()); //输出AnimalContainer`1

        Console.ReadKey();
    }
}

interface IAnimalContainer<out T>
{
    T GetAnimal();
}

class AnimalContainer<T> : IAnimalContainer<T> where T : Animal, new()
{
    public T GetAnimal()
    {
        Console.WriteLine("Create a {0}", typeof(T).Name);
        return new T();
    }
}

class Animal
{
}

class Cat : Animal
{
}

上面代码片段中定义了三个类AnimalCatAnimalContainer<T>AnimalCat是继承关系,AnimalContainer<T>为泛型接口IAnimalContainer<T>的实现类,并且AnimalContainer<T>类中的T的限制为继承Animal,并且具有默认公共构造函数。

Main方法中,我们定义了两个对象catContaineranimalContainer,分别是IAnimalContainer<Cat>IAnimalContainer<Animal>类型的,catContainer对象是具体类型AnimalContainer<Cat>的实例。然后我们将catContainer赋值给animalContainer,由于out关键字的使用,这行代码是合法的,可以成功编译。

最后我们输出了animalContainer对象的类型,结果是AnimalContainer,即像我们预期的类型成功变成了它的基类类型。这就是协变的示例。

逆变

逆变用于参数类型,表示一个方法的参数可以使用其基类型。使用in关键字可实现逆变。

示例2

class Program
{
    static void Main(string[] args)
    {
        IAnimalTracker<Cat> catTracker = new CatTracker();
        IAnimalTracker<Animal> animalTracker = catTracker;
        animalTracker.Track(new Animal());
        Console.ReadKey();
    }
}

interface IAnimalTracker<in T>
{
    void Track(T animal);
}

class CatTracker : IAnimalTracker<Cat>
{
    public void Track(Cat cat)
    {
        Console.WriteLine("Tracking a cat");
    }

    public void Track(Animal animal)
    {
        Console.WriteLine("Tracking an animal");
    }
}

class Animal
{
}

class Cat : Animal
{
}

上面代码片段中定义了三个类AnimalCatCatTrackerAnimalCat是继承关系,CatTracker为泛型接口IAnimalTracker<T>的实现类,并且IAnimalTracker<T>中的T使用in关键字实现逆变。

Main方法中,我们定义了两个对象catTrackeranimalTracker,分别是IAnimalTracker<Cat>IAnimalTracker<Animal>类型的,catTracker对象是具体类型CatTracker的实例。然后我们将catTracker赋值给animalTracker,由于in关键字的使用,这行代码是合法的,可以成功编译。

最后我们对animalTracker对象执行了Track方法,并且传入了一个具体类型为Animal的对象,运行结果仍然是Tracking a cat,我们传入的具体类型为Animal的参数成功转换为基类型Cat,这就是逆变的示例。

结论

协变和逆变是C#中非常有用的特性,可用于泛型和委托中。协变可用于返回类型,逆变可用于参数类型。当一个类型可以被替换为他的基类型或者继承类型时,我们可以使用协变或逆变。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:图文详解C#中的协变与逆变 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • MVC使用极验验证制作登录验证码学习笔记7

    下面是“MVC使用极验验证制作登录验证码学习笔记7”的完整攻略。 1. 简介 本文将以MVC模式为基础,介绍如何使用极验验证制作登录验证码。 2. 准备工作 在开始使用极验验证之前,需要先注册一个极验账号,并创建一个验证实例。具体步骤如下: 进入极验验证官方网站,点击“注册”按钮,填写相关信息,完成注册流程; 登录账号后,进入“验证管理”页面,创建一个验证实…

    C# 2023年5月31日
    00
  • c#判断数据库服务器是否已经启动的方法

    关于“c#判断数据库服务器是否已经启动的方法”,下面是完整的攻略: 1. 方法概述 在C#中,可以通过Ping类判断数据库服务器是否已经启动。Ping类是通过发送 Internet 控制消息协议 (ICMP) Echo 请求和接收 ICMP Echo 回应报文来测试连接的,可以用来测试远程主机是否可达。 2. 方法实现 在此提供一种实现思路:在C#中通过使用…

    C# 2023年6月2日
    00
  • 详解从零开始—用C#制作扫雷游戏

    详解从零开始—用C#制作扫雷游戏攻略 设计概述 在开始制作扫雷游戏之前,我们先来了解一下扫雷游戏的设计概述。 扫雷游戏主要由以下几个部分组成: 游戏界面:游戏界面包括扫雷游戏的棋盘、雷区、计时器、雷数显示等。 游戏规则:扫雷游戏的规则包括鼠标操作、雷的位置随机分布以及游戏结束判断等内容。 数据存储:扫雷游戏需要实现对游戏记录的存储与读取等功能。 下面我们…

    C# 2023年6月3日
    00
  • 不安装excel使用c#创建excel文件

    下面是不安装Excel使用C#创建Excel文件的完整攻略: 1. 基于Office Open XML格式的Excel文件创建 使用C#,我们可以使用Microsoft Office Open XML库来生成基于XML的Excel (.xlsx)文件。下面是一个示例代码: using System; using System.IO; using Docume…

    C# 2023年6月1日
    00
  • JSP动态输出Excel及中文乱码的解决

    JSP动态输出Excel及中文乱码的解决 在JSP中,我们可以使用POI库动态输出Excel文件,实现数据导出的功能。但是,在输出Excel文件时,中文字符可能会出现乱码的情况。本文将详细介绍JSP动态输出Excel及中文乱码的解决方法,包括代码实现和注意事项等。 步骤一:导入POI库 要使用POI库动态输出Excel文件,我们首先需要导入POI库。POI库…

    C# 2023年5月15日
    00
  • C#异常处理总结及简单实例

    C#异常处理总结及简单实例 本文介绍C#中异常处理的相关知识,包括什么是异常、异常的分类、异常的捕获和处理、如何自定义异常等内容,并通过示例代码进行演示说明。 什么是异常 在C#中,异常是指在程序运行时某些意料之外的问题导致程序无法继续执行的情况。比如:代码中试图打开不存在的文件,或是试图进行无效的计算等。在这些情况下,程序会抛出一个异常,来提示程序员有错误…

    C# 2023年6月6日
    00
  • 通用 HTTP 签名组件的另类实现方式

    以下是“通用HTTP签名组件的另类实现方式”的完整攻略: 什么是通用HTTP签名组件 通用HTTP签名组件是一种用于生成HTTP签名的组件,它可以帮助发送HTTP请求时验证请求的合法性。通用HTTP签名组件通常用于API认证和授权。 传统的通用HTTP签名组件实现方式 传统的通用HTTP签名组件实现方式通常是在HTTP请求头中添加签信息。以下是一个示例: G…

    C# 2023年5月12日
    00
  • C#:使用ffmpeg将图片合并成视频

      最近遇到公司的一个项目,需要将多张图片合并成一个播放的视频,找了很多资料和尝试了工具,遇到很多的坑,这里记下来,希望大家也能顺利解决遇到的问题。   合并视频,主要可以借用OpenCV 和 ffmpeg,这里是尝试用ffmpeg.exe的工具去实现图片文件合并成视频。   输入存储视频文件的路径,通过ProcessStartInfo 调用ffmpeg.e…

    C# 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部