协变(List泛型作为方法参数时的父类子类问题)

有段时间没搞.net的项目了(没办法,谁让国内JAVA流行是事实)。最近又回归.net(哪里需要哪里搬~)。

接收到需求后,一顿输出,结果…咦?编译失败???
在这里插入图片描述
错误信息:

CS1503:参数1:无法从"System.Collections.Generic.List<Student>" 转换为"Person"

额…仔细回想下(好久不搞.net,.net的理论知识都已经落灰了)。

下面是完整的测试代码:


public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
public class Student :Person
{
    public string School { get; set; }
    public decimal Score { get; set; }
}
public abstract class Point
{ 
    public Person person { get; set; }
    public List<Person> persons { get; set; }
    /// <summary>
    /// 单个
    /// </summary>
    public abstract void Info();

    /// <summary>
    /// 批量
    /// </summary>
    public abstract void List();
}

public class PointStudent : Point
{
    public PointStudent(Person data)
    {
        this.person = data;
    }
    public PointStudent(List<Person> data)
    {
        this.persons = data;
    }
    public override void Info()
    {
        Console.WriteLine($"{((Student)person).Name}就读于{((Student)person).School}");
    }
    public override void List()
    {
        this.persons.ForEach(p => { this.person = p; Info(); });
    }
}

static void Main(string[] args)
{
    Student student = new Student() { Name="张三",Age = 18,School ="东师"};
    Point point = new PointStudent(student);
    point.Info();

    List<Student> students = new List<Student>() { student };
    Point pointList = new PointStudent(students);
    pointList.List();
}

那么问题来了…

为什么使用子类的对象作为参数传入时没有错误?

答:

  • 后期绑定(Polymorphism):C# 支持后期绑定,这意味着在运行时确定方法的实际执行版本,而不是在编译时确定。

  • 继承和多态性:子类继承了基类的所有特性,同时可以拥有自己的特性和行为。当你将子类对象传递给期望基类类型的方法时,方法将根据子类对象的实际类型执行相应的操作。

为什么使用List时报错?

答:

  • 对于List和List,这是List类型,可以理解为2个不相干的类,不存在继承关系,所以不能直接作为参数传入。

怎么解决?

答:

  • 这里就用到了协变, 协变允许将一个派生类对象赋值给一个基类对象。

协变示例:


// Covariance.
IEnumerable<string> strings = new List<string>();  
// An object that is instantiated with a more derived type argument
// is assigned to an object instantiated with a less derived type argument.
// Assignment compatibility is preserved.
IEnumerable<object> objects = strings;

从C#4.0开始,IEnumerable 的声明中引入了 out 关键字,它表示这个接口支持协变性。


[TypeDependency("System.SZArrayHelper")]
[__DynamicallyInvokable]
public interface IEnumerable<out T> : IEnumerable
{
    [__DynamicallyInvokable]
    new IEnumerator<T> GetEnumerator();
}

那么上面这段代码该怎么修改?


public class Person
{
        public string Name { get; set; }
    public int Age { get; set; }
}

public class Student :Person
{
        public string School { get; set; }
    public decimal Score { get; set; }
}

public abstract class Point
{ 
    public Person person { get; set; }

    public IEnumerable<Person> persons { get; set; }
    /// <summary>
    /// 单个
    /// </summary>
        public abstract void Info();
    /// <summary>
    /// 批量
    /// </summary>
    public abstract void List();
}

public class PointStudent : Point
{
    public PointStudent(Person data)
    {
        this.person = data;
        }
    public PointStudent(IEnumerable<Person> data)
    {
        this.persons = data;
        }
    public override void Info()
    {
        Console.WriteLine($"{((Student)person).Name}就读于{((Student)person).School}");
        }
    public override void List()
    {
        this.persons.ForEach(p => { this.person = p; Info(); });
    }
}

static void Main(string[] args)
{
    Student student = new Student() { Name="张三",Age = 18,School ="东师"};
    Point point = new PointStudent(student);
    point.Info();

    List<Student> students = new List<Student>() { student };
    Point pointList = new PointStudent(students);
    pointList.List();
}

其实代码改动比较简单,大多数的程序员都知道该怎么去调整,这里我就多啰嗦了,需要注意的是:在岗位上拧螺丝的时候,不要忘了去回顾下自己的知识栈,保持技术的鲜活~


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/635401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云 EMR Serverless Spark 版开启免费公测

阿里云 EMR Serverless Spark 版是一款云原生&#xff0c;专为大规模数据处理和分析而设计的全托管 Serverless 产品。它为企业提供了一站式的数据平台服务&#xff0c;包括任务开发、调试、调度和运维等&#xff0c;极大地简化了数据处理的全生命周期工作流程。使用 EMR Serve…

win11安装MySQL

目录[-] 1. 1. 下载2. 2. 安装 参考文档&#xff1a;MySQL :: MySQL 8.4 Reference Manual 1. 下载 mysql官网下载msi安装程序&#xff1a;MySQL :: Begin Your Download 2. 安装 运行下载的mis程序,逐步安装。 安装模式&#xff1a; complete; 进入配置&#xff1a; data di…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权&#xff0c;可以让你生成有洞察力的、 简洁的、易于理解的SEO报告&#xff0c;帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

苹果CMS:如何去掉首页帮助提示信息

首先我们安装好苹果CMS&#xff0c;未安装的可以参考苹果cms&#xff1a;介绍及安装 安装好之后我们需要进入模版设置&#xff0c;可能对于刚刚接触CMS框架的朋友是不清楚地址的&#xff1a; https://www.yourweb.com/admin_login.php/admin/mxpro/mxproset 其中【yourweb】…

探索移动云:我的ES与Kibana之旅

目录 引言&#xff1a; 如何免费体验移动云产品 登录并完成实名认证 选择试用ECS云主机 安全组配置 安装Elasticsearch和Kibana 安装Elasticsearch ​编辑安装kibana 测试结果 使用感觉 引言&#xff1a; 移动云技术产品的发展已经取得了巨大的进步。云数融合、A1、大…

宝塔面包安装搭建Flarum开源论坛程序 文档教程

一、服务器环境说明 宝塔 7.0.3 或更新版本 Linux Server&#xff08;本文用的是 CentOs 7.4.6 64位&#xff09; Apache 或者 Nginx&#xff08;本文用的是 Nginx 1.16.0&#xff09; MySQL 5.6&#xff08;本文使用 MySQL 5.7&#xff0c;原因请看下方引用&#xff09; PHP 7…

weblogic ssrf漏洞(CVE-2014-4210)

漏洞复现环境搭建请参考 Vulhub漏洞复现环境搭建流程_vulhub一键搭建漏洞测试靶场,来进行漏洞复现-CSDN博客 docker未能成功启动redis请参考 http://t.csdnimg.cn/5osP3 漏洞版本 weblogic 10.0.2 -- 10.3.6.0 漏洞验证 &#xff08;1&#xff09;访问7001端口&#xff0c;…

基于MetaGPT构建单智能体

前言 在之前的文章中&#xff0c;我们详细地描述了Agent的概念和组成&#xff0c;在代码案例中体验了Agent的记忆、工具、规划决策模块&#xff0c;并通过几个Agent框架来加强读者对Agent开发设计与应用的理解&#xff0c;接下来我们就要进入智能体Agent的实际开发中&#xff0…

Linux系统Redhat7.4版本安装mysql-5.7.17详细步骤

1.1、在根目录创建一个data目录 mkdir /data 1.2、将MySQL安装包上传到/data目录下 1.3、解压MySQL安装包到当前目录 tar -zxvf mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz 1.4、因为解压后MySQL目录名称太长&#xff0c;修改成简短的mysql mv mysql-5.7.17-linux-glibc2.…

AI智能体|扣子Coze“图像流”功能速览

大家好&#xff0c;我是无界生长。 AI智能体&#xff5c;扣子Coze“图像流”功能速览Coze提供易上手的图像处理工作流&#xff0c;包含智能生成、智能编辑和基础编辑三类节点&#xff0c;旨在通过AI技术简化图像处理过程。本文对扣子Coze“图像流”功能做了简单介绍&#xff0…

爬虫学习--11.MySQL数据库的基本操作(上)

MySQL数据库的基本操作 创建数据库 我们可以在登陆 MySQL 服务后&#xff0c;使用命令创建数据库&#xff0c;语法如下: CREATE DATABASE 数据库名; 显示所有的数据库 show databases; 删除数据库 使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删…

基于EifficientNet的视网膜病变识别

分析一下代码 model.py ①下面这个方法的作用是&#xff1a;将传入的ch&#xff08;channel&#xff09;的个数调整到离它最近的8的整数倍&#xff0c;这样做的目的是对硬件更加友好。 def _make_divisible(ch, divisor8, min_chNone):if min_ch is None:min_ch divisornew…

爬虫学习--12.MySQL数据库的基本操作(下)

MySQL查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 语法&#xff1a;在MySQL数据库中查询数据通用的 SELECT 语法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 条件] [LIMIT N] 查询语句中你可以使用一个或者多个表&…

Ajax用法总结(包括原生Ajax、Jquery、Axois)

HTTP知识 HTTP&#xff08;hypertext transport protocol&#xff09;协议『超文本传输协议』&#xff0c;协议详细规定了浏览器和万维网服务器之间互相通信的规则。 请求报文 请求行: GET、POST /s?ieutf-8...&#xff08;url的一长串参数&#xff09; HTTP/1.1 请求头…

MySQL数据库单表查询中查询条件的写法

1.使用比较运算符作为查询条件 ; !; >; >; <; <; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;字段 from 表名 where Gender “M”; 即挑选出Gender “M” 的教师&#xff0c; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;…

如何使用Android NDK将头像变成“遗像”

看完本文的标题&#xff0c;可能有人要打我。你说黑白的老照片不好吗&#xff1f;非要说什么遗像&#xff0c;我现在就把你变成遗像&#xff01;好了&#xff0c;言归正传。我想大部分人都用过美颜相机或者剪映等软件吧&#xff0c;它们的滤镜功能是如何实现的&#xff0c;有人…

TCP Spurious Retransmission

TCP虚假重传是网络中可能存在丢包问题的一个指标&#xff0c;但并不意味着一定存在丢包。虚假重传指的是当TCP发送方错误地认为原始数据包已丢失时&#xff0c;会不必要地进行重传&#xff0c;而实际上原始数据包已成功到达目的地。 虚假重传可能由多种因素引起&#xff0c;例…

【Linux】进程信号及相关函数/系统调用的简单认识与使用

文章目录 前言一、相关函数/系统调用1. signal2. kill3. abort (库函数)4. raise (库函数)5. alarm 前言 现实生活中, 存在着诸多信号, 比如红绿灯, 上下课铃声…我们在接收到信号时, 就会做出相应的动作. 对于进程也是如此的, 进程也会收到来自 OS 发出的信号, 根据信号的不同…

分布式锁2-Zookeeper分布式锁实战

Zookeeper分布式锁实战 使用curator操作Zookeeper进行实战&#xff1b; curator是什么&#xff1a;Apache Curator包含一套高级API框架和工具类&#xff0c;它 是Apache ZooKeeper 的Java 客户端库。 准备 pom文件引入curtor依赖和zookeeper依赖 <!--curator--> <…

麦克纳母轮(全向)移动机器人集群控制的Simulink/Simscape虚拟仿真平台搭建

麦克纳姆轮是一种常见的全向移动机构&#xff0c;可以使机器人在平面内任意方向平移&#xff0c;同时可以利用差速轮车的属性实现自转&#xff0c;能够在狭窄且复杂多变的环境中自由运行&#xff0c;因而被广泛应用于竞赛机器人和特殊工业机器人场景。 Ps:最新的BYD仰望U8也有一…