深拷贝与浅拷贝是很多语言都有的概念,在C#中也不例外
1. 深拷贝与浅拷贝
深拷贝与浅拷贝的区别就是在拷贝的时候是否会建立一个新的对象实体还是引用。而比较直观的就是浅拷贝时,修改拷贝对象的值会改变原对象的值,因为他们在内存里仍然是同一块区域,而浅拷贝修改拷贝对象的值并不会影响原对象的值。
在Python中有copy和deepcopy方法,在c++中可以通过重载构造函数和等号实现拷贝的实际行为,在Rust可以通过trait实现复制语义和移动语义,当然移动语义和复制语义有别于深拷贝与浅拷贝。那么Rust中如何实现深拷贝呢?那么首先我们需要认识C#中的值类型和引用类型。
2. C#类型系统
类型、变量和值
C# 是一种强类型语言。 每个变量和常量都有一个类型,每个求值的表达式也是如此。 每个方法声明都为每个输入参数和返回值指定名称、参数数量以及类型和种类(值、引用或输出)。 .NET 类库定义了一组内置数值类型以及表示各种逻辑构造的更复杂类型(如文件系统、网络连接、对象的集合和数组以及日期)。 典型的 C# 程序使用类库中的类型,以及对程序问题域的专属概念进行建模的用户定义类型。
类型中可存储的信息包括以下项:
- 类型变量所需的存储空间。
- 可以表示的最大值和最小值。
- 包含的成员(方法、字段、事件等)。
- 继承自的基类型。
- 它实现的接口。
- 在运行时分配变量内存的位置。
- 允许执行的运算种类。
编译器使用类型信息来确保在代码中执行的所有操作都是类型安全的。 例如,如果声明 int 类型的变量,那么编译器允许在加法和减法运算中使用此变量。 如果尝试对 bool 类型的变量执行这些相同操作,则编译器将生成错误,如以下示例所示:
int a = 5;
int b = a + 2; //OK
bool test = true;
// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
int c = a + test;
备注:
C 和 C++ 开发人员请注意,在 C# 中,bool 不能转换为 int。
编译器将类型信息作为元数据嵌入可执行文件中。 公共语言运行时 (CLR) 在运行时使用元数据,以在分配和回收内存时进一步保证类型安全性。
在变量声明中指定类型
当在程序中声明变量或常量时,必须指定其类型或使用 var 关键字让编译器推断类型。 以下示例显示了一些使用内置数值类型和复杂用户定义类型的变量声明:
// Declaration only:
float temperature;
string name;
MyClass myClass;
// Declaration with initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = {
0, 1, 2, 3, 4, 5 };
var query = from item in source
where item <= limit
select item;
方法声明指定方法参数的类型和返回值。 以下签名显示了需要 int 作为输入参数并返回字符串的方法:
public string GetName(int ID)
{
if (ID < names.Length)
return names[ID];
else
return String.Empty;
}
private string[] names = {
"Spencer", "Sally", "Doug" };
声明变量后,不能使用新类型重新声明该变量,并且不能分配与其声明的类型不兼容的值。 例如,不能声明 int 后再向它分配 true
的布尔值。 不过,可以将值转换成其他类型。例如,在将值分配给新变量或作为方法自变量传递时。 编译器会自动执行不会导致数据丢失的类型转换。 如果类型转换可能会导致数据丢失,必须在源代码中进行 显式转换。
内置类型
C# 提供了一组标准的内置类型来表示整数、浮点值、布尔表达式、文本字符、十进制值和其他数据类型。 还有内置的 string
和 object
类型。 这些类型可供在任何 C# 程序中使用。 有关内置类型的完整列表,请参阅内置类型。
自定义类型
可以使用结构、类、接口,和枚举构造创建你自己的自定义类型。 .NET 类库本身就是 Microsoft 提供的一组自定义类型,以供你在自己的应用程序中使用。 默认情况下,类库中最常用的类型在任何 C# 程序中均可用。 对于其他类型,只有在显式添加对定义这些类型的程序集的项目引用时才可用。 编译器引用程序集之后,你可以声明在源代码的此程序集中声明的类型的变量(和常量)。 有关详细信息,请参阅 .NET 类库。
通用类型系统
对于 .NET 中的类型系统,请务必了解以下两个基本要点:
- 它支持继承原则。 类型可以派生自其他类型(称为 基类型)。 派生类型继承(有一些限制)基类型的方法、属性和其他成员。 基类型可以继而从某种其他类型派生,在这种情况下,派生类型继承其继承层次结构中的两种基类型的成员。 所有类型(包括 System.Int32C# 关键字:int等内置数值类型)最终都派生自单个基类型,即