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

在这里插入图片描述

文章目录

  • Object
    • Equals
    • GetType
    • ToString
    • GetHashCode
  • string
    • 逐字文本
    • 复合格式字符串
    • 字符串内插
  • StringBuilder
    • StringBuilder 的工作原理
    • StringBuilder提供的方法
    • 访问字符
    • 迭代字符
    • 查询字符
  • dynamic


Object

支持 .NET 类层次结构中的所有类,并为派生类提供低级别服务。 这是所有 .NET 类的最终基类;它是类型层次结构的根。

简单来说,它是万能的,它是所有类型的父类。因为.NET 中的所有类都派生自 Object,因此 Object 类中定义的每个方法都可用于系统中的所有对象。

在 Object 类中提供了 4 个常用的方法,即 Equals、GetHashCode、GetType 以及 ToString 方法。

Equals

int a = 1;
int b = 1;
if (a.Equals(b))
{Debug.Log("111"); -- 输出111
}Person a = new Person();
Person b = 1;
if (a.Equals(b))
{Debug.Log("111"); -- 输出111
}

Equals是相等判断,与==相同,对于值类型的判断是否值相同,而对于引用类型则判断是否引用相同。

GetType

用于获取当前实例的类型,返回值为 System.Type 类型。GetType 方法不含任何参数,是非静态方法。

使用Object.GetType()来返回对象的类型x.GetType()和typeof()的区别是,GetType()是object的方法,可以用于所有变量后,以获取它们的类型。和typeof(xxx)内部只能放类型而不能放变量名。

ToString

将对象转换为其字符串表示形式,使其适合显示。

上述三种方法是可以重载,重写的。

GetHashCode

返回对象的哈希值,每个对象的哈希值都是固定的。该方法不含有任何参数,并且不是静态方法,因此需要使用实例来调用该方法。由于该方法是在 Object 类中定义的,因此任何对象都可以直接调用该方法。


string

字符串类型string表示零个或多个 Unicode 字符的序列。 比较特殊的是,尽管string是引用类型,但是使用==来比较时却是值类型的比较。需要注意的是,string是不可变类型,这意味着每次我们修改字符串string的操作实际上都是创建了一个新的字符串。

逐字文本

使用@关键字标识该字符串为逐字文本,将不会识别转义符

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

复合格式字符串

使用String.Format方法将变量复合到格式项内,其中括号内的数字代表了对应的变量索引,而:后面代表变量的指定类型。

String.Format("Name = {0}, hours = {1:hh}", name, DateTime.Now);

多个相同索引也可以同时存在

string multiple = String.Format("0x{0:X} {0:E} {0:N}",Int64.MaxValue);
Console.WriteLine(multiple);
// The example displays the following output:
//      0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00

字符串内插

使用$关键字标识字符串内插

string name = "Mark";
var date = DateTime.Now;
// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");

(更多用法请阅读官方文档,尤其是string类的方法,尴尬的是string类的方法特别多,但是String大多数情况下却被StringBuilder完爆)


StringBuilder

使用命名空间System.Text来引入该类型

StringBuilder可以说是String的完全上位替代,这是一个可变的字符串类。 可变性意味着,创建类的实例后,可以通过追加、删除、替换或插入字符对其进行修改。由于String每次修改时都需要产生一个新的字符串,这也就导致了对其进行操作可能产生的一些内存消耗问题。所以对于需要操作的字符串,我们会选择StringBuilder,不过性能取决于字符串的大小、要为新字符串分配的内存量、执行代码的系统以及操作的类型。

请考虑在以下情况下使用 String 类:

  • 当代码对字符串进行的更改数较小时。 在这些情况下, StringBuilder 可能会提供微不足道的性能改进,或者没有性能 String改进。
  • 执行固定数量的串联操作时,尤其是字符串文本。 在这种情况下,编译器可能会将串联操作合并到单个操作中。
  • 在生成字符串时必须执行广泛的搜索操作时。 类 StringBuilder 缺少搜索方法,例如 IndexOf 或 StartsWith。 对于这些操作,必须将 对象转换为 StringBuilder , String 这可以抵消使用 StringBuilder的性能优势。 有关详细信息,请参阅 在 StringBuilder 对象中搜索文本 部分。

请考虑在以下情况下使用 StringBuilder 类:

  • 如果预期代码在设计时对字符串进行未知数量的更改, (例如,使用循环连接包含用户输入) 的随机数量的字符串时。
  • 预期代码对字符串进行大量更改时。

总的来说,一些短平快的操作,或者需要涉及串联字符串,或是查询整个字符串的时候更适合String。如果一些需要频繁更改,或者动态修改的字符串更适合StringBuilder

StringBuilder 的工作原理

StringBuilder是如何动态修改字符串长度的?假设有一个字符串长度为16的stringBuilder,如果我们需要Append成一个length =20的字符串,那么首先StringBuilder会把字符串丢入这个长度为16的缓冲区,当长度超过缓冲区的长度时,则意味着需要更大的缓冲区,则StringBuilder会找一个缓冲区大小翻一倍的新缓冲区(现在是32了)。然后把旧缓冲区的值复制过去,并加入那些超过原长度而未被存入旧缓冲区的新字符。如果还是超过就重复上述过程,直到存储完毕为止。(如果超出了设定最大容量或者内存没有多余空间了则报错)

public class Example
{public static void Main(){StringBuilder sb = new StringBuilder();ShowSBInfo(sb);sb.Append("This is a sentence.");ShowSBInfo(sb);for (int ctr = 0; ctr <= 10; ctr++) {sb.Append("This is an additional sentence.");ShowSBInfo(sb);}   }private static void ShowSBInfo(StringBuilder sb){foreach (var prop in sb.GetType().GetProperties()) {if (prop.GetIndexParameters().Length == 0)Console.Write("{0}: {1:N0}    ", prop.Name, prop.GetValue(sb));}Console.WriteLine();}
}
// The example displays the following output:
//    Capacity: 16    MaxCapacity: 2,147,483,647    Length: 0
//    Capacity: 32    MaxCapacity: 2,147,483,647    Length: 19
//    Capacity: 64    MaxCapacity: 2,147,483,647    Length: 50
//    Capacity: 128    MaxCapacity: 2,147,483,647    Length: 81
//    Capacity: 128    MaxCapacity: 2,147,483,647    Length: 112
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 143
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 174
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 205
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 236
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 267
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 298
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 329
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 360

StringBuilder提供的方法

可以进行单独的方法调用并忽略返回值,如以下示例所示。

using System;
using System.Text;public class Example
{public static void Main(){StringBuilder sb = new StringBuilder();sb.Append("This is the beginning of a sentence, "); sb.Replace("the beginning of ", ""); //替换所有字符A为字符Bsb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ");sb.Replace(",", "."); Console.WriteLine(sb.ToString());}
}
// The example displays the following output:
//        This is a complete sentence.

可以在单个语句中调用一系列方法。 如果要编写链接连续操作的单个语句,这可以很方便。 以下示例将上一示例中的三个方法调用合并到一行代码中。

using System;
using System.Text;public class Example
{public static void Main(){StringBuilder sb = new StringBuilder("This is the beginning of a sentence, ");sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, "complete ").Replace(",", ".");Console.WriteLine(sb.ToString());}
}
// The example displays the following output:
//        This is a complete sentence.

访问字符

访问字符在我看来是StringBuilder的一大痛点。StringBuilder没有提供访问其内部字符的方法,而想要访问其中的某个字符却没那么简单,因为缓冲区的内存是不连续的,如果想要找到某个字符,我们就需要遍历整个缓冲区。因此较好的方法是通过ToString方法将其转化为String类型之后使用char[Index]去访问对应字符。

迭代字符

当迭代StringBuilder的字符的时候,应当注意:即使对于大型“区块” StringBuilder 对象,使用 Chars[] 属性进行基于索引的访问一个或少量字符的性能影响可以忽略不计;通常,这是 一个 O (n) 操作。 当迭代 StringBuilder 对象中的字符时,会对性能造成显著的影响,这是 O(n^2) (遍历n个字符*缓存区容量n)操作。

因此当我们需要迭代StringBuilder的字符时,较好的方法还是通过ToString方法将其转化为String类型之后使用char[Index]去访问对应字符。

查询字符

在StringBuilder中并没有提供查询字符的方法,想实现查询字符,也只能转为String,然后用String.IndexOf或者String.StartWith方法查找对应的字符或字符串。

由于String和StringBuilder提供的方法太多,因此此处无法深入,推荐阅读官方文档


dynamic

最后稍微了解一下dynamic动态类型。dynamic本身也是一个Object。在大多数情况下,dynamic 类型与 object 类型的行为类似。 具体而言,任何非 Null 表达式都可以转换为 dynamic 类型。 dynamic 类型与 object 的不同之处在于,编译器不会对包含类型 dynamic 的表达式的操作进行解析或类型检查。 编译器将有关该操作信息打包在一起,之后这些信息会用于在运行时评估操作。 在此过程中,dynamic 类型的变量会编译为 object 类型的变量。 因此,dynamic 类型只在编译时存在,在运行时则不存在。

dynamic的特殊就在于它是不会在编译时被解析的,因此不会进行任何的安全检查。因此即使定义了错误的dynamic,编译器也不会报错。而只有在运行时出现错误才会报错。

其次,由于dynamic的本质是Object,它也可以和任何类型进行隐式转换。而这也是它的最大优点。例如:

dynamic x = 10; //此时x为int
x = x + "Hello"; // x 现在是一个字符串
x = x.ToUpper(); // x 仍然是一个字符串
x = 8;  // x 现在保存的是一个int类型的变量
x = x * 8; // x现在仍然是int

在上例中,我们定义x为dynamic,可以看出来它对应应当是int型,然后我们将其转化为字符串,然后对字符串进行操作。随后又把x赋值为了int类型的。x在整个程序中动态的变动它的类型。而这是var做不到的,因为var关键字下编译器会自动地推断它的类型,那它就是一个静态类,一般没有显示转换的前提下我们是不能进行类型转换的。

如果只用静态类想实现则需要新创建其中设计到的静态类型对应的变量,而如果想让静态类型变量x实现上述过程只会更加复杂:

int x=10;
String y = x.ToString();
y=y+"Hello";
y = y.ToUpper();
x = 8;
x = x* 8

而dynamic的动态类型实际和某些脚本语言的变量性质是非常相似的。因此我们也使用dynamic类型来与脚本语言进行对接。

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

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

相关文章

Python实现GA遗传算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

全面解析大语言模型的工作原理

当ChatGPT在去年秋天推出时&#xff0c;在科技行业乃至世界范围内引起了轰动。当时&#xff0c;机器学习研究人员尝试研发了多年的语言大模型&#xff08;LLM&#xff09;&#xff0c;但普通大众并未十分关注&#xff0c;也没有意识到它们变得多强大。 如今&#xff0c;几乎每个…

无代码开发(BIP旗舰版-YonBuilder)

目录 我的应用 新建领域 菜单管理 应用构建 新建应用 对象建模 新增业务对象 新增业务实体 页面建模 新增页面 编辑页面 发布管理 我的应用 角色管理 yonbuilder开发平台&#xff0c;提供标准服务和专业开发服务&#xff1b; 本篇文章只演示标准服务的可视化应用…

Flink State 和 Fault Tolerance详解

有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态&#xff0c;这就使得状态在整个Flink的精细化计算中有着非常重要的地位&#xff1a; 记录数据从某一个过去时间点到当前时间的状态信息。以每分钟/小时/天汇总事件时&#xff0c;状态将保留…

弹性布局,网格布局,JavaScript

弹性盒子布局&#xff08;Flexbox Layout&#xff09;&#xff1a;通过display: flex;设置容器为弹性盒子&#xff0c;可以实现更复杂的自适应和响应式布局。 网格布局&#xff08;Grid Layout&#xff09;&#xff1a;通过display: grid;设置容器为网格布局&#xff0c;可以将…

Unity 引擎做残影效果——2、屏幕后处理方式

Unity实现残影效果 大家好&#xff0c;我是阿赵。 这里继续介绍Unity里面做残影的方法。之前介绍了BakeMesh的方法做残影&#xff0c;这一期介绍的是用屏幕后处理的方法做残影。 一、原理 之前的BakeMesh方法&#xff0c;是真的生成了很多个网格模型在场景里面。如果用后处理做…

day49-Springboot

Springboot 1. Springboot简介 1.1 简介&#xff1a;Springboot来简化Spring应用开发的一个框架&#xff0c;约定大于配置 1.2 优点&#xff1a; 可以快速的构建独立运行的Spring项目&#xff1b; 框架内有Servlet容器&#xff0c;无需依赖外部&#xff0c;所以不需要达成w…

正则匹配img标签里面src

正则&#xff1a; (?<src\s*\s*\")\S(?\"{1})匹配效果&#xff1a;

Ansible —— playbook 剧本

Ansible —— playbook 剧本 一、playbook的概述1.playbook简介2.什么是Ansible playbook剧本&#xff1f;3.Ansible playbook剧本的特点4.如何使用Ansible playbook剧本&#xff1f;5.playbooks 本身由以下各部分组成 二、playbook示例1.运行playbook2.定义、引用变量3.指定远…

HarmonyOS/OpenHarmony元服务开发-卡片使用动效能力

ArkTS卡片开放了使用动画效果的能力&#xff0c;支持显式动画、属性动画、组件内转场能力。需要注意的是&#xff0c;ArkTS卡片使用动画效果时具有以下限制&#xff1a; 以下示例代码实现了按钮旋转的动画效果&#xff1a; Entry Component struct AttrAnimationExample { St…

Vue axios + Vue使用

相对于原生的阿贾克斯&#xff0c;axios提供的方法使用起来会更加的简便&#xff0c;之前网络数据获取到了&#xff0c;如何和vue一起使用呢&#xff1f; 网络应用的核心就是data中的数据一部分是通过网络获取到的。所以在方法当中发起网络请求&#xff0c;在响应回来之后将服…

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 (…

【腾讯云Cloud Studio实战训练营】使用Cloud Studio迅捷开发一个3D家具个性化定制应用

目录 前言&#xff1a; 一、腾讯云 Cloud Studio介绍&#xff1a; 1、接近本地 IDE 的开发体验 2、多环境可选&#xff0c;或连接到云主机 3、随时分享预览效果 4、兼容 VSCode 插件 5、 AI代码助手 二、腾讯云Cloud Studio项目实践&#xff08;3D家具个性化定制应用&…

探索 GPTCache|GPT-4 将开启多模态 AI 时代,GPTCache + Milvus 带来省钱秘籍

世界正处于数字化的浪潮中&#xff0c;为了更好理解和分析大量数据&#xff0c;人们对于人工智能&#xff08;AI&#xff09;解决方案的需求呈爆炸式增长。 此前&#xff0c;OpenAI 推出基于 GPT-3.5 模型的智能对话机器人 ChatGPT&#xff0c;在自然语言处理&#xff08;NLP&a…

【MYSQL】MYSQL学习笔记【基础篇】【未完待续】

文章目录 MYSQL入门一、MYSQL概述1. 数据库相关概念1.1 数据库&#xff0c;数据库管理系统与SQL1.2 数据库种类以及主流数据库管理系统排名1.3 MySQL数据库安装1.4 数据模型 二、SQL2.1 通用语法与注释2.2 SQL分类2.3 图形化界面2.4 DDL2.4.1 数据库操作2.4.2 表操作2.4.2.1 表…

介绍一下JS垃圾回收机制

JavaScript中的垃圾回收机制负责自动管理内存&#xff0c;回收不再使用的对象所占用的内存空间。在JavaScript中&#xff0c;开发者不需要显式地分配和释放内存&#xff0c;垃圾回收器会自动完成这些操作。以下是关于JavaScript垃圾回收机制的一些关键概念&#xff1a; 内存生命…

Linux下基于Dockerfile构建镜像应用(1)

目录 基于已有容器创建镜像 Dockerfile构建SSHD镜像 构建镜像 测试容器 可以登陆 Dockerfile构建httpd镜像 构建镜像 测试容器 Dockerfile构建nginx镜像 构建镜像 概述&#xff1a; Docker 镜像是Docker容器技术中的核心&#xff0c;也是应用打包构建发布的标准格式。…

云曦暑期学习第三周——ctfshow--php特性(89-104)

目录 web89 preg_match函数 、数组 web90 intval()函数、强比较 web91 正则修饰符 web92 intval()函数、弱比较 web93 八进制、小数点 web94 strpos() 函数、小数点 web95 小数点 web96 highlight_file() 下的目录路径 web97 数组 web98 三目运算符 web9…

chrome扩展在popup、background、content之间通信解决传输文件问题

文章目录 背景介绍案例介绍代码示例popup页面&#xff0c;上传文件页面popup页面&#xff0c;js上传代码&#xff0c;file文件转base64background监听消息&#xff0c;base64转file文件&#xff0c;axios上传 附-转base64后直接下载 背景介绍 示例扩展API版本MV2。 以弹…

利用openTCS实现车辆调度系统(一)系统介绍

系统介绍 openTCS简介 官方的回答&#xff1a; openTCS&#xff08;开放式运输控制系统的缩写&#xff09;是一种免费的控制系统软件&#xff0c;用于协调自动导引车&#xff08;AGV&#xff09;和移动机器人车队&#xff0c;例如在生产工厂中。 通常应该可以控制任何具有通信…