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

相关文章

  • C# 表达式树Expression Trees的知识梳理

    下面是关于“C# 表达式树 Expression Trees的知识梳理”的攻略。 什么是表达式树? 表达式树是一种数据结构,用于表示代码中的表达式。在C#中,每个表达式都可以转换成一个表达式树。表达式树实际上是一个表达式的对象表示形式,其包含了表达式的所有元素,如运算符、操作数和子表达式。 为什么要使用表达式树? 表达式树有许多应用场景,其中最常见的用途是L…

    C# 2023年6月1日
    00
  • C# 崩溃异常中研究页堆布局的详细过程

    C# 崩溃异常中研究页堆布局的详细过程 在C#的开发过程中,可能会遇到程序崩溃的情况。其中,页堆布局可能是导致崩溃的原因之一。本文将详细讲解页堆布局的研究过程。 什么是页堆布局? 页堆布局是指在Windows操作系统中,进程使用内存的方式。在这种布局模式下,进程会申请一块连续的虚拟地址空间,并将其分割成大小相等的内存块(通常为4KB)。这些内存块被映射到实际…

    C# 2023年5月14日
    00
  • VS2015 C#生成dll文件的方法(32/64)

    生成dll文件是C#程序开发中的常见需求之一,下面是在VS2015中生成32/64位dll文件的完整攻略。 生成32位dll文件的攻略 打开Visual Studio 2015软件,点击File -> New -> Project,创建一个新的Class Library项目。 在“Solution Explorer”窗口中右键单击项目名称,选择“…

    C# 2023年5月14日
    00
  • C#、ASP.NET通用扩展工具类之LogicSugar

    首先感谢您对LogicSugar工具类的关注与使用,下面详细讲解一下该工具类的完整攻略。 一、概述 LogicSugar是一款C#、ASP.NET通用扩展工具类库,主要提供了一些常用的快捷方法和扩展类,帮助C#和ASP.NET开发者快速高效地完成开发工作。LogicSugar的特点是简单易用、代码量少、维护性强、可以更加方便地扩展使用。 二、安装和使用 Lo…

    C# 2023年5月15日
    00
  • C#验证用户输入信息是否包含危险字符串的方法

    当用户提交输入信息时,应该进行对输入信息进行过滤,排除包含有恶意的、危险的字符串,避免安全问题的发生。本文将详细讲解 C# 验证用户输入信息是否包含危险字符串的方法。 步骤1:安装 Microsoft.Security.Application 库 Microsoft.Security.Application 是一个 .Net FrameWork 库,提供了一…

    C# 2023年5月15日
    00
  • ASP.NET Core中的Razor页面使用视图组件

    在 ASP.NET Core 中,可以使用 Razor 页面和视图组件来构建动态 Web 应用程序。视图组件是一种可重用的 UI 组件,可以在多个 Razor 页面中使用。以下是 ASP.NET Core 中 Razor 页面使用视图组件的完整攻略: 步骤一:创建视图组件 在使用视图组件前,需要创建视图组件。可以在 ASP.NET Core 项目中的 Vie…

    C# 2023年5月17日
    00
  • C#使用log4net打日志

    当开发大型项目时,通常需要在软件中记录日志以便于后期查看、分析和定位问题。log4net是一个开源的日志记录框架,可用于C#应用程序中。本文将介绍如何使用log4net在C#应用程序中记录日志。 安装log4net 首先需要安装log4net。可以通过NuGet包管理器安装log4net,也可以手动下载log4net的二进制文件。 NuGet安装方法如下: …

    C# 2023年5月15日
    00
  • C# 数组中的 indexOf 方法及使用

    C# 数组中的 indexOf 方法及使用 在C#中,数组是一种非常常见的数据结构,它们可以用来存储多个相同类型的数据。我们可以使用indexOf方法来查找指定元素在数组中的索引位置。 indexOf 方法的语法 indexOf方法用于查找数组中指定元素的位置,语法如下: public static int indexOf(Object[] array, O…

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