【C#学习笔记】引用类型(1)

news2024/11/17 23:52:02

在这里插入图片描述

文章目录

  • 引用类型
    • class
      • 匿名类
    • 记录
      • 引用相等和值相等
      • record声明
    • 接口
    • delegate 委托
      • 合并委托/多路广播委托


引用类型

引用类型的变量存储对其数据(对象)的引用,而值类型的变量直接包含其数据。 对于引用类型,两种变量可引用同一对象;因此,对一个变量执行的操作会影响另一个变量所引用的对象。 对于值类型,每个变量都具有其自己的数据副本,对一个变量执行的操作不会影响另一个变量(in、ref 和 out 参数变量除外)。

在前文中,我们常常说引用类型比值类型要好,一方面引用类型的对象类似于指针,不同的变量会指向同一个对象。而值类型则是将定义的值克隆一个副本赋值给新的变量。从性能方面引用类型就更好,并且从内存方面考虑,引用类型存放在CLR的虚拟机堆中,而值类型存放在栈中,在堆中可以对数据直接处理,而在栈中则需要将其前面的内存出栈,从内存方面使用引用类型也更好。而具体的关于引用和值类型在内存中的关系,将在未来GC的章节中描述。

在这里插入图片描述


class

类应该是最熟悉的一种引用类型了

class ClassA { } --直接定义类
class DerivedClass : BaseClass { } --继承单个类
class ImplClass : IFace1, IFace2 { } -- 实现两个接口
class ImplDerivedClass : BaseClass, IFace1 { } --继承一个类,实现一个接口

在C#中,我们只能继承一个类,但是可以继承多个接口。(看到本文,我默认你学过面向对象了)

匿名类

匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。 类型名由编译器生成,并且不能在源代码级使用。 每个属性的类型由编译器推断。

var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);  //108Hello

使用匿名类,我们定义新的对象的时候可以不必定义一个类,这是为了方便我们进行一些对象的生成,特别是当这个类是临时定义的,只需要属性而不需要其他方法,且有可能只会定义一次对象的时候。

匿名类型包含一个或多个公共只读属性。 包含其他种类的类成员(如方法或事件)为无效。 用来初始化属性的表达式不能为 null、匿名函数或指针类型。

在下例中,我们用prod遍历了products集合,并在每次创建一个新的匿名类,其中属性为Color和Pirce

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

尽管我们并没有给匿名类中的属性创建变量名,但是匿名类自动的将创建时的变量名作为了自己的变量名,也就是创建时使用了prod.Color,prod.Price。它根据变量名为自己的属性也创建了相应的同名变量ColorPrice

还可以按另一种类型(类、结构或另一个匿名类型)的对象定义字段。 它通过使用保存此对象的变量来完成,如以下示例中所示,其中两个匿名类型是使用已实例化的用户定义类型创建的。 在这两种情况下,匿名类型 shipment shipmentWithBonus 中的 product 字段的类型均为 Product,其中包含每个字段的默认值。 bonus 字段将是编译器创建的匿名类型。

var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };

在上述例子中我们可以看到,匿名类本身的属性通常不需要定义类型,而类型是由编译器自己决定的。而已有类型定义的变量则是其对应的类型,例如product的类型是Product,而bonus的类型则是匿名类。
由于匿名类的类型是不定的,因此使用var关键字来定义这个匿名类。

如果想要修改匿名类中的属性,可以使用with表达式来实现:

var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
var Banana = apple with {}; // 使用with空值可以直接赋值

(注意,with和record只能在C# 9以上的版本使用,unity中暂时不可用)


记录

记录是一个类或者结构体,通过添加record修饰符声明,

在下列情况下,请考虑使用记录而不是类或结构:

  • 你想要定义依赖值相等性的数据模型。
  • 你想要定义对象不可变的类型。

值相等性的意思是两个作为相等比较的值,只有当它们类型相等,且属性的属性名相等且属性值相等,才能视为相等。类似于内部的键值对需要完全相等。更具体的来说,一般而言的相等性是引用相等性,其相等比较在于:如果两个类型引用同一个变量则认为它们相等。

不可变性就是在对象实例化后禁止更改该对象的任何属性或字段值。

引用相等和值相等

为了清楚引用相等和值相等,请看下面几个例子:

Product A = new Product();
Product B = new Product();
if (A == B)
{
   Debug.Log(1);  --输出不了
}

第一个例子中,A==B是false的,因为A和B作为引用类型,它们的引用不相等

Product A = new Product();
Product B = A;
if (A == B)
{
   Debug.Log(1);  --输出1
}

在第二个例子中,B引用A,而A引用的是new Product(),所以二者引用相等。

值相等应当不必解释了,就是平常意义上的相等

record声明

var phoneNumbers = new string[2];
Person person1 = new("Nancy", "Davolio", phoneNumbers);
Person person2 = new("Nancy", "Davolio", phoneNumbers);
Console.WriteLine(person1 == person2); // output: True

person1.PhoneNumbers[0] = "555-1234";
Console.WriteLine(person1 == person2); // output: True

Console.WriteLine(ReferenceEquals(person1, person2)); // output: False

接口

接口是高度抽象的,我们可以使用interface关键字定义一个接口,在接口中我们只应当定义函数头,其内部实现则完全由继承了接口的类来实现。

interface IEquatable<T>
{
    bool Equals(T obj);
}

一个接口同样可以继承其他的接口,当一个接口继承多个其他接口后,这个接口被称为派生接口,其他接口被称为基接口。一个继承了派生接口的类,不仅需要实现派生接口中的所有方法,也需要实现基接口中的所有方法:

interface IBaseInterface
{
    void BaseMethod();
}
interface IEquatable : IBaseInterface
{
    bool Equals();
}
public class TestManager : IEquatable
{
    bool IEquatable.Equals()
    {
        throw new NotImplementedException();
    }
    void IBaseInterface.BaseMethod()
    {
        throw new NotImplementedException();
    }
}

delegate 委托

委托的使用通常需要将方法作为参数传递给其他方法时。可以将委托视为调用一个事件时会触发的方法。相当于我们不必在事件或者函数内部定义一个回调参数,而只需要把委托方法附加上去即可。

相较于接口,委托更适合灵活的方法组合,可以添加给多个事件。用我个人的理解来比喻,点餐是一个事件,假设这个饭店能APP点餐和服务员点餐,而APP只能点套餐,服务员可以一个菜一个菜给你加。现在我们分别要用委托和接口实现这个事件。委托像是有个服务员帮你点餐,你只需要说想吃什么,服务员就会帮你记下然后通知后厨。而接口像捆绑了一堆的套餐,如果点了鸡腿套餐,那一定会给你鸡腿+米饭,点了猪排套餐一定给你猪排+米饭。而使用委托,如果我们想要鸡腿+米饭,我们也可以让服务员给我们增加两个菜(方法),一个是鸡腿,一个是米饭。但是如果我们想要的菜品多,且和套餐重复的话,那么接口可以更好的实现。但如果我们想要灵活地点菜,例如我想要鸡腿+米饭,用接口实现了,然后我又想要一个猪排,如果用接口实现那接口会给我猪排+米饭。如果我只想要猪排那就应该叫服务员来,只点一个猪排。

委托可以和方法绑定,当触发委托时自动触发绑定的方法

// Declare a delegate:
delegate void Del(int x);

// Define a named method:
void DoWork(int k) { /* ... */ }

// Instantiate the delegate using the method as a parameter:
Del d = obj.DoWork;

合并委托/多路广播委托

不同的委托之间可以合并:

CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;

hiDel = Hello;
byeDel = Goodbye;
multiDel = hiDel + byeDel;
multiMinusHiDel = multiDel - hiDel;

委托的合并直接使用加法即可,简单来说委托A+委托B =合并委托C,而合并委托C可以使用减法把委托A或者委托B减掉。加法就像服务员A和服务员B跟厨师说1号桌要XXX菜,2号桌要XXX菜,厨师肯定是哪桌先点餐哪桌先上菜。减法就是服务员B过来又说2号桌不要了,你别做了,那厨师只做服务员A委托的1号桌的菜就好了。

在调用多播委托时,它会按顺序调用列表中的委托。 只能合并相同类型的委托。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【分布式任务调度平台 XXL-JOB 急速入门】从零开始将 XXL-JOB 接入到自己的项目

&#x1f4a7; 分布式任务调度平台 X X L − J O B 急速入门&#xff1a;从零开始将 X X L − J O B 接入到自己的项目 \color{#FF1493}{分布式任务调度平台 XXL-JOB 急速入门&#xff1a;从零开始将 XXL-JOB 接入到自己的项目} 分布式任务调度平台XXL−JOB急速入门&#xff1a…

在.net 6.0中 调用远程服务器web服务,Webservices(xxx.asmx) ,RESTful 风格,2种解决方案。

1.使用 Connected Services&#xff1a; 右键单击您的项目&#xff0c;选择 "Add"&#xff08;添加&#xff09;-> "Connected Services"&#xff08;已连接的服务&#xff09;。 在 "Connected Services" 对话框中&#xff0c;选择 "W…

如何用 Apache DolphinScheduler 实现自动配置自定义变量?

作者 | sqlboy-yuzhenc 背景介绍 在实际工作应用中&#xff0c;我们可能需要在整个 Apache DolphinScheduler 层面定义共用的日期变量&#xff0c;但是&#xff0c;开源版 Apache DolphinScheduler 只允许配置工作流级别的全局变量&#xff0c;这样&#xff0c;每个工作流就得…

机器学习笔记之优化算法(九)收敛速度的简单认识

机器学习笔记之优化算法——收敛速度的简单认识 引言收敛速度的判别标准 Q \mathcal Q Q-收敛速度 R \mathcal R R-收敛速度关于算法复杂度与收敛速度 引言 本节对收敛速度简单介绍。 收敛速度的判别标准 我们之前几节介绍了线搜索方法 ( Line Search Method ) (\text{Line …

无人驾驶实战-第四课(动态环境感知与2D检测算法)

无人驾驶中的检测框架 2D目标检测的思路 位置&#xff1a;先找到所有的ROI (Region of Interest, bounding box may containing object)类别&#xff1a;对每一个ROI做分类获取类别信息 位置修正&#xff1a;Bounding box Regression 找寻ROI的方法 1.滑窗法。从左到右&#xf…

Ansys Zemax | 大功率激光系统的 STOP 分析 (三)

大功率激光器广泛用于各种领域当中&#xff0c;例如激光切割、焊接、钻孔等应用中。由于镜头材料的体吸收或表面膜层带来的吸收效应&#xff0c;将导致在光学系统中由于激光能量吸收所产生的影响也显而易见&#xff0c;大功率激光器系统带来的激光能量加热会降低此类光学系统的…

Java中的内存划分,一个数组的内存图,两个数组的内存图,两个引用指向同一个数组的内存图

1、Java中的内存划分 Java的内存需要分成5个部分&#xff1a; 栈&#xff08;Stack&#xff09; 存放的都是 方法 中的 局部变量 。方法的运行一定要在栈当中运行。 局部变量&#xff1a;方法的参数&#xff0c;或者是方法{}内部的变量 作用域&#xff1a;一旦超出作用域&#…

ubuntu调整路由顺序

Ubuntu系统跳转路由顺序 1、安装ifmetric sudo apt install ifmetric2、查看路由 route -n3、把Iface下面的eth1调到第一位 sudo ifmetric eth1 0命令中eth1是网卡的名称&#xff0c;更改网卡eth1的跃点数&#xff08;metric值&#xff09;为0&#xff08;数值越小&#xf…

存放数据的方式:Java集合框架

文章目录 1. 目前存放数据的方式2. Java集合框架3. Collection接口常用方法解析public boolean add(E e)public void clear()public boolean remove(E e)public boolean contains(E e)public boolean isEmpty()public int size()public Object[] toArray() 4. 迭代器5. 增强for…

从零基础开始开发自己的第一个微信小程序

文章目录 内容介绍小程序开发步骤注册微信小程序账号下载开发工具搭建开发环境创建工程编写代码手机上查看效果 工程里的文件作用介绍总结 内容介绍 通过本篇blog&#xff0c;你可以熟悉从零开始&#xff0c;搭建小程序开发环境&#xff0c;并运行起自己的第一个小程序。 小程…

Stability AI旗舰图像模型 SDXL1.0发布,AI绘画进入新的时代

Stability AI于7月26号开源了SDXL1.0文生图模型&#xff0c;要知道距离SDXL0.9开源发布也不过一个月,只能说AI发展日新月异。 根据官网介绍&#xff0c;SDXL1.0经过迭代更新&#xff0c;已经是目前世界上最好的图像生成模型 官网根据Discord上的几代实验模型和外部测试&#…

股票量价关系分析

量增价平 量增价平是指成交量增加&#xff0c;股价保持相对平稳的量价关系模型&#xff0c;量的增加可以是资金大量流入引起&#xff0c;也可以是资金大量流出引起&#xff0c;因此这种关系模型需要根据股价所处的位置来具体分析。1、股价处于低位 当股价处于低位&#xff0c;此…

Unity之webgl端通过vue3接入腾讯云联络中心SDK

腾讯云联络中心SDK:云联络中心 Web-SDK 开发指南-文档中心-腾讯云 (tencent.com) 1 首先下载Demo ​ 1.1 对其进行解压 ​ 1.2根据文档操作 查看README.md,根据说明设置server下的dev.js里的相关参数。 然后打开电脑终端&#xff0c;cd到项目的路径&#xff1a; ​ 安装…

喜报 | 《中国AIOps现状调查报告(2023)》发布!擎创科技案例再度入选

&#xff08;本文部分内容来自《中国AIOps现状调查报告&#xff08;2023&#xff09;》&#xff0c;丝小编扣1&#xff0c;领取完整版报告&#xff09; 2023年7月18日&#xff0c;信通院Xops产业创新发展论坛于北京成功举办。大会旨在提高企业研发运营水平&#xff0c;加强XOp…

243. 一个简单的整数问题2(树状数组)

输入样例&#xff1a; 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4输出样例&#xff1a; 4 55 9 15 解析&#xff1a; 一般树状数组都是单点修改、区间查询或者单点查询、区间修改。这道题都是区间操作。 1. 区间修改用数组数组维护差分数组 2. 区间查询&am…

实现弧形切角两种方式

1、css 的 radial-gradient <view style"padding:30px; background: #ccc;"><view class"navActive"></view> </view>.navActive{width: 200px;height: 40px;background-color: #fff;color: rgb(0,63,136);position: relative;bor…

windows环境下安装elasticsearch、kibana

通过本文可以快速在windows系统上安装elasticsearch、kibana环境。 当你用Integer类型的时候&#xff0c;要非常小心&#xff0c;因为100等于100、但是200不等于200&#xff0c;当然&#xff0c;如果你会一点小花招&#xff0c;也可以让100不等于100、让200等于200。(运算符比较…

优化供应链和库存管理:PDM系统的物料控制之道

在现代制造业中&#xff0c;优化供应链和库存管理是企业实现高效运营和降低成本的重要目标。PDM系统作为一款强大的数字化工具&#xff0c;扮演着物料控制之道的角色&#xff0c;帮助企业实现优化供应链和库存管理的目标。让我们一同深入探讨&#xff0c;看看PDM系统是如何通过…

git clone 登录 github

git clone 登录 github 目录概述需求&#xff1a; 设计思路实现思路分析1.github 设置setting2.输入passwd 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result…

mac切换jdk版本

查询mac已有版本 1、打开终端&#xff0c;输入&#xff1a; /usr/libexec/java_home -V注意&#xff1a;输入命令参数区分大小写(必须是-V) 2.目前本地装有两个版本的jdk xxxxedydeMacBook-Pro-9 ~ % /usr/libexec/java_home -V Matching Java Virtual Machines (2):20.0.1 (…