目录
一.转义序列
转义符
在C#中,字符转义序列(也称为转义符)是用来表示特殊字符的一种方式.当你需要在字符串中插入特殊字符,如换行符、制表符或引号时,就需要使用转义序列
转义字符序列是一条指令,指示运行时插入会影响字符串输出的特殊字符.在 C# 中,转义字符序列以反斜杠 \
开头,后跟要转义的字符
例如:\n序列为添加一个新行(可以简单理解为换行)\t序列将添加一个制表符
Console.WriteLine("Hello\nWorld!");
Console.WriteLine("Hello\tWorld!");
如果运行代码,将会看到以下输出:
Hello
World!
Hello World!
我们在日常编码中还可能碰到类似这样的需求:
控制台打印Hello "World" !
如果这时我们运行代码
Console.WriteLine("Hello "World"!"); //错误示例
就会产生编译错误 ,这个时候就需要我们用到转义字符
Console.WriteLine("Hello \"World\ "!");
\"表示插入一个双引号字符,运用转义字符正确在文本内容中插入引号
如果不运用转义字符,会让编译器混淆,认为你想要提前终止字符串,这样就会产生编译错误
以下是C#中一些常见的转义序列及其含义:
转义字符 | 含义 |
\n - 新行(newline) | 插入一个新行 |
\t - 制表符(tab) | 插入一个水平制表符 |
\" - 双引号 | 插入一个双引号字符 |
\' - 单引号 | 插入一个单引号字符 |
\\ - 反斜杠 | 插入一个反斜杠字符 |
\r - 回车(carriage return) | 将光标移回到行首 |
\0 - 空字符(null character) | 插入一个空字符 |
\a - 警告(bell) | 发出警告声(如果终端支持的话)。 |
\b - 退格(backspace) | 移动光标到前一个位置,通常用于覆盖前一个字符 |
\f - 换页(form feed) | 插入一个换页符 |
\v - 垂直制表符 | 插入一个垂直制表符 |
\uXXXX - Unicode 字符 | 插入一个由四位十六进制数表示的 Unicode 字符 |
\xHH - ASCII 字符 | 插入一个由两位十六进制数表示的 ASCII 字符 |
逐字字符串
在C#中,逐字字符串是一种特殊的字符串表示方式,它允许你直接插入路径或包含特殊字符的字符串,而不需要使用转义序列.逐字字符串通过在其前缀添加一个@符号来定义.
语法使用:逐字字符串语法使用很简单,只需要在字符串前面加上@符号即可.
特点:
1.不解析转义序列
逐字字符串中的所有字符都被视为原样,即使它们是转义序列也不会被解析.例如,@字符后面的 \n
不会被解释为换行符
string str = @"This string contains a backslash \ and a newline \n.";
Console.WriteLine(str); //控制台输出This string contains a backslash \ and a newline \n.
2.路径处理
逐字字符串非常适合处理文件路径,因为它们允许你直接插入路径,而不需要使用转义序列。这对于包含反斜杠 \
的路径特别有用。
string filePath1 = @"C:\Users\John\Documents\file.txt"; //使用逐字字符串
string filePath2 = "C:\\Users\\John\\Documents\\file.txt"; //使用转义字符
Console.WriteLine(filePath1==filePath2);//True
以上两种写法路径完全一样但是如果我们使用逐字字符串可以稍微简洁一点
3.多行字符串
逐字字符串可以跨越多行,这对于编写HTML代码或XML文档等非常有用,因为你可以直接在字符串中插入换行符.
string str = @"This is a multi-line string.
It can span multiple lines,
and it's very useful for HTML or XML.";
Console.WriteLine(str);
这时候我们在控制台打印输出的结果为
This is a multi-line string.
It can span multiple lines,
and it's very useful for HTML or XML.
二.字符串拼接
字符串拼接的概念:字符串拼接是将两个或者多个字符拼接起来形成一个新的字符串的过程.
1.使用+运算符
使用+运算符是最常见的字符串拼接方式之一,它简单直观,适用于拼接少量的字符串
示例:
//1.使用 + 运算符
string str1 = "Hello";
string str2 = "World";
string str3 = str1 + " " + str2;
Console.WriteLine(str3); //输出:Hello World
2.使用string.Format方法
//2.使用 string.Format 方法
string str1 = "Hello";
string str2 = "World";
// 使用 string.Format 方法拼接字符串
string str4 = string.Format("{0} {1}", str1, str2);
// 输出结果
Console.WriteLine(str4); // 输出 "Hello World"
//定义占位符:
//在 string.Format 方法中,使用 {0}, {1}, {2}, 等来定义占位符。这些数字对应于传递给 string.Format 方法的参数的位置。
//参数列表:
//在 string.Format 方法中,紧跟在格式字符串之后的是一个参数列表,这些参数将按照顺序替换格式字符串中的占位符。
//输出结果:
//在上述示例中,str1 和 str2 分别是 "Hello" 和 "World"。string.Format 方法将 {0} 替换为 str1 的值,将 {1} 替换为 str2 的值,最终得到 "Hello World"。
3.使用string.Concat方法
string str1 = "Hello";
string str2 = "World";
// 使用 string.Concat 方法拼接字符串
string str5 = string.Concat(str1, " ", str2);
// 输出结果
Console.WriteLine(str5); // 输出 "Hello World"
//使用 string.Concat 方法:
//string.Concat 方法接受一个或多个字符串参数,并返回一个新的字符串,它是所有参数的连接。
//参数列表:
//在上述示例中,string.Concat 方法接收三个参数:str1、一个空格 " " 和 str2。
//输出结果:
//str1 的值是 "Hello",str2 的值是 "World"。string.Concat 方法将这三个参数连接起来,形成一个新的字符串 "Hello World"。
4.使用插值字符串
string str1 = "Hello";
string str2 = "World";
// 使用插值字符串拼接字符串
string str6 = $"{str1} {str2}";
// 输出结果
Console.WriteLine(str6); // 输出 "Hello World"
//使用 $ 符号:
//插值字符串以 $ 符号开始,这告诉编译器接下来是一个格式化字符串。
//嵌入表达式:
//在插值字符串中,可以使用 {} 来嵌入表达式,表达式的结果会被转换为字符串并插入到最终的字符串中。
//输出结果:
//在上述示例中,str1 的值是 "Hello",str2 的值是 "World"。{str1} 和 {str2} 分别被替换为这两个变量的值,中间有一个空格 " " 作为分隔符,最终得到的字符串是 "Hello World"。
5.使用StringBuilder类
string str1 = "Hello";
string str2 = "World";
// 创建 StringBuilder 实例
StringBuilder sb = new StringBuilder();
// 使用 Append 方法拼接字符串
sb.Append(str1);
sb.Append(" ");
sb.Append(str2);
// 获取最终的字符串
string str7 = sb.ToString();
// 输出结果
Console.WriteLine(str7); // 输出 "Hello World"
//创建 StringBuilder 实例:
//使用 new StringBuilder() 创建一个新的 StringBuilder 实例。
//使用 Append 方法:
//StringBuilder 类提供了 Append 方法来添加字符串。在这个例子中,我们使用 sb.Append(str1) 添加了 str1 的值,接着添加了一个空格 " ", 然后使用 sb.Append(str2) 添加了 str2 的值。
//获取最终的字符串:
//使用 sb.ToString() 方法将 StringBuilder 对象转换为字符串。
6.使用string.Join方法
string str1 = "Hello";
string str2 = "World";
// 创建一个字符串数组
string[] arr = { str1, str2 };
// 使用 string.Join 方法拼接字符串
string str8 = string.Join(" ", arr);
// 输出结果
Console.WriteLine(str8); // 输出 "Hello World"
//创建字符串数组:
//使用花括号 { } 创建一个字符串数组 arr,并将 str1 和 str2 作为数组的元素。
//使用 string.Join 方法:
//string.Join 方法的第一个参数是一个分隔符,本例中使用了一个空格 " "。第二个参数是字符串数组 arr。
//输出结果:
//string.Join 方法将数组中的每个字符串用空格分隔,并返回一个新的字符串,即 "Hello World"。
注:string.Join方法主要用于连接数组中的元素,但它也可以用于连接其他类型的枚举类型
三.值类型
在C#中,值类型是一种直接存储数据值的类型.这意味着当一个值类型变量被赋值时,变量中存储的是实际的数据值,而不是指向数据的引用.值类型包括基本类型(如 int,double,bool等),结构体(struct)和枚举(enum)
值类型的特点:
1.存储在栈中
值类型通常存储在栈中,这意味着它们的内存分配和释放非常快。
当一个值类型变量被声明时,它的内存空间立即被分配,并且当变量不再使用时,该内存空间会被立即释放。
2.按值传递
当值类型作为参数传递给方法时,实际上是传递了一个副本。这意味着方法内的修改不会影响到原始变量。
这意味着值类型变量在函数调用时是独立的,不会受到外部修改的影响。
3.不可为空
值类型不允许为null,除非它是可空类型
如果一个值类型变量没有被显式初始化,则默认值为该类型的零值,例如 0 对于数值类型,false
对于布尔类型,或者 default(T)
对于结构体类型
结构体
结构体是用户定义的值类型。它们可以包含字段、属性、方法、构造函数等。结构体与类类似,但它们是值类型,而不是引用类型。
示例:
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
枚举
枚举是一种特殊的值类型,它提供了一种方便的方式来定义一组命名常量。
示例:
public enum DaysOfWeek
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
可空类型
格式:数据类型? 变量名称 = 初始值;
? 单问号用于对 int、double、bool 等无法直接赋值为 null 的数据类型进行 null 的赋值,意思是这个数据类型是 Nullable 类型的
int? i = 3;
//Nullable<int> i = new Nullable<int>(3);//等同于第一行代码
int ii; //默认值0
int? iii; //默认值null
可空类型的特点:
1.允许为null:
可空类型变量可以被赋值为null,这使得值类型能够表示缺失的值
2.值类型基础:
可空类型本质上仍然是值类型,这意味着它们仍然存储在栈中。
可空类型实际上是一个结构体,它包含了两个成员:一个是值类型的成员,另一个是一个布尔值,用于指示是否设置了值。
3.值和HasValue属性:
可空类型提供了一个Value属性来访问存储的值,一个HasValue属性用于检查值是否已经被设置.
4.默认值:
如果一个可空类型的变量没有被显式初始化,那么它的默认值为null
5.值类型转换:
可以将一个可空类型转换为其对应的非可空类型,但需要注意转换之前要检查HasValue,也可以将一个非可空类型转换为可空类型
四.引用类型
引用类型的特点
1.存储在堆中
引用类型的数据通常存储在堆中,而引用本身存储在栈中.
当一个引用类型变量被声明时,它的内存空间会在堆中分配,而栈中则保存指向这个堆内存的引用.
2.按引用传递
当引用类型作为参数传递给方法时,传递的是引用的副本.这意味着方法内的修改会影响到原始变量,
同时意味着引用类型变量在函数调用时是共享的,可以在方法内部修改原始对象的状态.
3.可以为null
引用类型可以被赋值为null,表示没有任何引用对象
常见的引用类型
1.类
类是最常用的引用类型之一,可以用来定义复杂的数据结构。
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
2.接口
接口定义了一个类必须实现的方法、属性和事件的签名。
interface IShape
{
double Area { get; }
}
3.数组
数组也是一种引用类型,即使它们由值类型组成。
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
4.委托
委托可以被视为指向方法的引用。
delegate void MyDelegate(string message);
引用类型与值类型有何不同
值类型变量将其值直接存储在名为堆栈的存储区域中。 堆栈是为 CPU 上当前运行的代码分配的内存(也称为堆栈帧或激活帧)。 堆栈帧执行完毕后,堆栈中的值将被删除。
引用类型变量将其值存储在名为堆的单独内存区域中。 堆是一个内存区域,由操作系统上运行的多个应用程序同时共享。 .NET 运行时与操作系统进行通信以确定可用的内存地址,并请求可存储该值的地址。 .NET 运行时会存储值,然后将内存地址返回给变量。 当代码使用变量时,.NET 运行时会无缝查找变量中存储的地址,并检索其中存储的值。