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

yizhihongxing

图文详解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日

相关文章

  • 用c# 自动更新程序

    做程序开发的朋友们都应该遇到过这样的问题,当你编写了一个程序并部署到用户端时,如果程序需要进行升级,你会面临一个很棘手的问题,那就是如何快速地将新版本的程序部署到用户端,并让用户端程序可以自动升级到最新版本?这就需要我们使用C#来编写一个自动更新程序。 以下是用C#实现自动更新程序的完整攻略: 1. 程序自身升级功能实现 在程序中添加自我升级功能,可以通过以…

    C# 2023年6月1日
    00
  • C#利用Task实现任务超时多任务一起执行的方法

    下面我将为你详细讲解“C#利用Task实现任务超时多任务一起执行的方法”的完整攻略。 1. 使用Task.WaitAny方法实现超时控制 在C#中,使用Task可以很方便地实现多任务并行执行,但是如果需要控制任务的执行时间,避免超时等问题,则需要使用Task.WaitAny方法。具体步骤如下: 步骤1:启动多个任务 首先,我们需要启动多个任务,让它们并行执行…

    C# 2023年6月6日
    00
  • Windows窗体的.Net框架绘图技术实现方法

    了解Windows窗体的.Net框架绘图技术 在Windows窗体的.Net框架中,绘图功能可以通过System.Drawing命名空间中的类实现,如Pen、Brush、Graphics等类。Graphics类是最常用的绘图工具之一,它可以在屏幕、打印机和图像上进行绘制操作。以下是实现绘图操作的基本步骤: 创建Graphics对象 创建Pen或Brush对象…

    C# 2023年5月31日
    00
  • .NetCore MemoryCache使用详解

    在.NET Core中,我们可以使用MemoryCache来缓存数据。在本攻略中,我们将详细讲解如何使用MemoryCache来缓存数据,并提供两个示例说明。 注册MemoryCache:首先,需要在.NET Core项目中注册MemoryCache。我们可以在Startup.cs文件中的ConfigureServices方法中添加以下代码: public …

    C# 2023年5月16日
    00
  • .net core利用PdfSharpCore操作PDF实例教程

    .NET Core利用PdfSharpCore操作PDF实例教程 简介 PdfSharpCore是一个.NET Core实现的PDF库,它提供基本的PDF操作,如创建、编辑和添加内容到PDF文件等。在本教程中,我们将使用PdfSharpCore来创建、编辑和保存PDF文件。 安装 我们通过NuGet安装PdfSharpCore。可以在Visual Studi…

    C# 2023年6月3日
    00
  • Asp.net Core Jenkins Docker实现一键化部署的实现

    Asp.net Core Jenkins Docker实现一键化部署的实现 在本攻略中,我们将深入讲解如何使用Asp.net Core、Jenkins和Docker实现一键化部署,并提供两个示例说明。 准备工作 在开始之前,您需要完成以下准备工作: 安装Docker和Docker Compose。 安装Jenkins并配置好.NET Core插件。 创建一个…

    C# 2023年5月17日
    00
  • C#6.0新语法示例详解

    C#6.0新语法示例详解攻略 简介 C#6.0是微软为.NET开发者带来的一个重要的版本,其中包含了很多新的语法特性,这些新特性可以让开发者更加方便地书写代码,提高代码的可读性和可维护性。 本篇攻略将会对C#6.0中的一些新语法特性进行详细讲解,包括:Null-conditional运算符、string的插值、nameof表达式、Auto-property初…

    C# 2023年5月15日
    00
  • .net core如何使用Redis发布订阅

    .NET Core中使用Redis发布订阅攻略 在 .NET Core 中,我们可以使用 Redis 发布订阅功能来实现消息传递和事件通知。本攻略将介绍如何在 .NET Core 中使用 Redis 发布订阅功能。 步骤 以下是使用 Redis 发布订阅功能的步骤: 安装 Redis。 在服务器上安装 Redis。可以使用官方网站提供的安装包或者使用包管理器…

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