C#图解教程第3章_类型与函数参数

1. 预定义类型和用户定义类型

1)预定义类型

   C#提供16种预定义类型,如下图所示。

C#图解教程第3章_类型与函数参数

    tips:

  • 与C++不一样,数值类型不具有布尔类型,如C++ 可以int a= 3,可以if(a)..;C#不行。
  • dynamic类型在动态语言中使用,使用dynamic可以自定义添加不存在的属性和值,编译不会对它进行类型检查。var与之不同,对于var,编译器会自动为其替换对应类型。

 2)用户定义类型

   c#提供了6种用户定义类型:class,struct,array,enum,delegate,interface.

2. 值类型、引用类型,值参数,引用参数

1)堆和栈

   介绍值参数和引用参数前,先介绍堆和栈的概念。堆和栈是指运行程序时,使用的存储数据的两个内存区域。栈是一个内存数组,遵循LIFO(后进先出)的数据结构,栈一般存储如下数据:

  • 某些类型变量的值;
  • 程序当前的执行环境
  • 传递给方法的参数

  栈的示意图如下:

C#图解教程第3章_类型与函数参数

 堆也是一块内存区域,它相当于栈很大,一般用于存储大型数据,堆内数据能以任意顺序存入和删除。
 堆的示意图如下:

C#图解教程第3章_类型与函数参数

2)值类型和引用类型

值类型:存储在栈上;
引用类型:类似于C++的指针,引用存储在栈上,实际数据存储在堆上。

C#图解教程第3章_类型与函数参数

C#的值类型和引用类型分类如下图:

C#图解教程第3章_类型与函数参数

tips:

  • 对于值类型,它也有可能在堆上。如在类中(引用类型)定义了值类型,那么在类实例中,该值类型数据,还是在堆中,如下图(MyType类中定义了一个值类型A):
  • 值类型都是struct,都继承于System.ValueType类,CLR对System.ValueType的派生类做了特殊处理,如使它内存分配方面具有值类型的特征,使其不能被继承(私有)等。

C#图解教程第3章_类型与函数参数

3. 值参数和引用参数

    值参数:在方法调用时,在栈上先为形参分配空间,然后将实参的值复制给形参。
    引用参数:类似于C++的引用,在方法调用的时候,不会在内存中分配空间,只会为实参分配一个别名。

tips:

  • 引用参数声明和调用时必须都使用ref。
  • 引用参数的实参必须是变量,且用做实参时必须被赋值(防止未被赋值时,报错,相对于C++的改进),COM编码时调用时可省略ref,需传一个值(非变量)。
  • string比较特殊,虽然是引用类型,但作为值参传入函数时,string类型的变量在被赋予新值的时候,不会将原值擦去而填上新的值,而是会在堆中重新开辟空间,在空间中放入新的值,从而变量的地址也会改变,变成新空间的地址。

4.可空类型

   某些情况下,你希望表示变量目前未保存有效值,对于引用类型可以用null表示,对于值类型,可以在定义时再类型后加上?,就也可以null表示未保存有效值;

int? a = null;

Nullable<int> a = null;