C#引用类型
引用类型概述:
引用类型变量存储的是数据的内存地址,而不是数据本身。主要包括类、接口、委托、数组等。
字符串
string 字符串类型:用于存储多个字符,是不可变的引用类型。
三种方式
string str = ”12313“ ; //直接写法 比较方便string str1 = @”12313“; //@写法 不用考虑转义字符string str2 = $“123123”; //$方便连接
转义字符
\n (换行)
\r
\t (制表符)
\f
\"
\\
\b
\'
说明:字符串对象一旦创建,其内容不可修改。每次对字符串的操作(如拼接、替换)都会生成新的字符串对象。
string s1 = "Hello";
string s2 = s1 + " World"; // s1不变,s2是新字符串
字符串常用方法
方法 | 描述 | 示例 |
---|---|---|
Length | 获取字符串长度 | string s = "abc"; s.Length |
Substring | 提取子字符串 | s.Substring(1, 2) 返回"bc" |
Contains | 判断是否包含子字符串 | s.Contains("ab") → true |
Replace | 替换字符串 | s.Replace("a", "A") |
Split | 分割字符串 | "a,b,c".Split(',') |
Trim | 去除首尾空白字符 | " abc ".Trim() → "abc" |
object 类型 对象类型
object是所有类型的父类型,object类型的变量,可以存储任意类型的数据
是所有类型的基类,可以存储任意类型的数据。
类型检查在编译时进行。
object o1 = "123";o1 = 123;o1 = true;
可以定义自己的类(生成自己的对象) 存储一系列相关的数据
object
常用方法
GetType()
:获取对象的运行时类型。
ToString()
:返回对象的字符串表示。
Equals()
:比较对象是否相等(需注意引用相等与值相等的区别)。
列如:记录班级同学中每一学生的信息 姓名 年龄 性别 学号 爱好.......
class Stundent{public string Name { get; set;}pubilc int Age {get;set;}public Sexenum Sex {get;set}public enum Sexenum{Man,Wonman}}
动态类型(dynamic)
dynamic 也可以存储任意类型的数据
dynamic dy1 = 300dy1 = true;dy1 = “shaio” ;
dynamic 动态类型 类型的校验,在运行的时候进行校验(类型错误也可以保存运行)
object 对象类型虽然也可以保存任意类型的数据,但是它的类型校验在编译期间(类型错误不可保存运行)
var 自动推导类型,根据初始数值自动推导类型,在编译期间确定类型
var number = 10;
装箱和拆箱(会影响程序执行流程)
装箱:值类型转换为引用类型
拆箱:引用类型转换为值类型
装箱:值类型 → 引用类型(需在堆上分配内存,性能开销大)。
拆箱:引用类型 → 值类型(需类型检查,可能抛出InvalidCastException
)。
建议:避免频繁装箱拆箱,优先使用泛型集合(如List<T>
)。
内存存储
值类型存储在栈中
值类型的变量,可以直接分配给一个值,直接复制值,直接保存值本身
引用类型存储在堆中
引用类型的变量,不包含存储在变量中的实际数据,直接存储值的地址,
=运算符 在进行赋值操作的过程中是栈内存中的内容
=运行符 在进行复制操作的过程中是复制栈中操作的内容
对象的属性也可以是一个对象
内存分配对比
特性 | 引用类型(如class ) | 值类型(如struct ) |
---|---|---|
存储位置 | 堆(Heap) | 栈(Stack)或对象内 |
复制方式 | 复制引用(指向同一对象) | 复制值(创建独立副本) |
空值支持 | 可赋值null | 不可赋值null (除非是可空类型) |
性能 | 堆分配 / 回收开销大 | 栈分配 / 回收快 |
典型应用场景
引用类型:复杂对象(如List<T>
、自定义类)
值类型:轻量级数据结构(如Point
、DateTime
)
结构体(struct)
结构体也可以让变量存储多个数据(值类型),用法和形式与类基本相同,可以理解为:结构体是值类型的对象
结构体也分为两步
1.结构体的声明
2.结构体的创建
struct Book{public string Name;public int Age;}
与类(class)的区别
特性 | 结构体(struct) | 类(class) |
---|---|---|
类型 | 值类型 | 引用类型 |
继承 | 不能继承 / 被继承 | 可继承、实现接口 |
默认构造函数 | 自动生成,不可自定义 | 可自定义构造函数 |
内存效率 | 栈分配,适合高频使用场景 | 堆分配,适合复杂对象 |
示例:定义带方法的结构体
struct Point
{public int X { get; set; }public int Y { get; set; }
public double DistanceToOrigin() => Math.Sqrt(X * X + Y * Y);
}
类型转换
隐式转换:从小到大
显示转换:从大到小
不是所有的类型都可以转换,如char和string的转换
Tostring() 转换为字符串
int.Pares() 转换为整数
bool.Pares() 转换为布尔值
Convert 转换数据类型的类
安全转换方法
as 运算符:引用类型转换,失败返回null(不抛出异常)
object obj = "hello";
string str = obj as string; // 成功则返回字符串,失败返回null
is运算符:类型检查。
if (obj is string s) { /* 使用s */ }
Convert
类:支持多种类型间的安全转换(如Convert.ToInt32()
)。
自定义类型转换
通过implicit
和explicit
关键字定义类型转换运算符:
public class Meter
{public double Value { get; set; }
// 隐式转换:Meter → Kilometerpublic static implicit operator Kilometer(Meter m) => new Kilometer { Value = m.Value / 1000 };
}
异常处理
异常类型层次
System.Exception
是所有异常的基类。
常见异常类:NullReferenceException
、ArgumentException
、DivideByZeroException
等。
finally
块的执行时机
无论try
块是否抛出异常,finally
块中的代码总会执行(即使try
或catch
中有return
语句)。
使用using
语句简化资源管理
对于实现了IDisposable
接口的对象(如文件流、数据库连接),可使用using
自动释放资源:
using (FileStream fs = new FileStream("test.txt", FileMode.Open))
{// 使用fs读取文件
} // 离开作用域时自动调用fs.Dispose()
8. 引用类型的高级特性
匿名类型
临时存储一组只读属性,无需显式定义类。
var person = new { Name = "Alice", Age = 30 };
Console.WriteLine(person.Name); // 输出:Alice
委托(Delegate)
引用类型,可封装方法(类似函数指针)。
delegate int MathOperation(int a, int b);
MathOperation add = (a, b) => a + b;
Console.WriteLine(add(3, 4)); // 输出:7
垃圾回收(GC)
引用类型对象由 GC 自动回收,需注意避免内存泄漏(如静态集合持有对象引用)。
总结对比表
类型 | 存储位置 | 复制方式 | 空值支持 | 典型场景 |
---|---|---|---|---|
string | 堆 | 引用复制 | 支持 | 文本处理 |
object | 堆 | 引用复制 | 支持 | 泛型存储、反射 |
dynamic | 堆 | 引用复制 | 支持 | 动态语言交互、JSON 解析 |
struct | 栈 / 对象内 | 值复制 | 不支持 | 轻量级数据结构 |
自定义类(class) | 堆 | 引用复制 | 支持 | 复杂业务对象 |