值类型:包括整数,小数,字符,布尔值,枚举,结构体,用户定义的值类型等,存储在栈中
引用类型:包括指针,字符串,数组,类,接口,已装箱的值类型,委托等,其引用部分存储在栈中,引用指向的内容存储在堆中。
关于栈和堆的存储:
(1)当建立了一个引用的引用时,如字符串数组,其最高层级的引用部分存储在栈中,它指向的次级引用依然存储在堆中,次级引用指向的内容自然也存储在堆中。
代码示例:
namespace ZB
{
class Program
{
static void Main(string[] args)
{
string[] strs = new string[3];
strs[0] = "ab";
strs[1] = "cd";
strs[2] = "ef";
int num = 2;
string s = "gh";
string s2 = strs[0];
}
}
}
内存图展示:
(2)栈中的内容会在其所在的局部代码区域(如函数中或大括号括起来的代码段)结束时,自动释放内存。C#堆中的内容会在失去其栈中的引用时,自动被C#的回收机制所释放,无需程序员人工管理。
强制类型转换(显示转换):高精度(位数多)向低精度(位数少)转换
自动类型转换(隐式转换):低精度(位数少)向高精度(位数多)转换
代码实例:
namespace ZB
{
class Program
{
static void Main(string[] args)
{
int a = 1234567;
string c = Convert.ToString(a, 2);
//强制转换
short b = (short)a;//本实例中可看出int转换给short的十六位就是int的末端16位
//隐式转换
int d = b;//自动转换时,也将整数低位的数据自动赋给高精度数据的末端位
Console.WriteLine(c);
//输出:100101101011010000111
Console.WriteLine(b);
//-10617,刚好对应int末16位的补码转换值
Console.WriteLine(d);
//-10617,说明d的末端位接收了b的数据位
Console.ReadLine();
}
}
}
is:对象 is 类型名,类型既可以是值类型也可以是引用类型,当对象属于该类型时,这个整体返回布尔值true,不属于时则返回false。
as:对象 as 类型名,类型只能是引用类型,若属于该类型,则原封不动的返回对象本身,不属于该类型则返回NULL(但测试时发现不属于该类型时编译器直接报错)。
代码实例:
namespace ZB
{
class Class1
{
public int b=0;
}
class Program
{
static void Main(string[] args)
{
int a = 10;
if (a is int)
{
Console.WriteLine("a是int类型");
}
else if (a is string)
{
Console.WriteLine("a是string类型");
}
Class1 c1 = new Class1();
string s = "asd";
if(c1 as Class1!= null)
{
Console.WriteLine("c1是Class1类型");
}
/*else if(c1 as string != null)//编译器直接报错
{
Console.WriteLine("c1是string类型");
}*/
Console.ReadLine();
}
}
}
装箱:值类型转换成引用类型
int a=20; Object b=(Object)a;//装箱,发生堆内存分配。可以不使用显示转换,直接用隐式转换就行:Object d=a;
拆箱:引用类型转换成值类型
int c = (int)b;//拆箱,使用上两行代码中的b