1. 先填空再验证:
struct SomeVal { public int x; }
class SomeRef { public int x; }
class SomeRef2 { public SomeVal val; }
class SomeVal3 { public SomeRef rf; }
public static void Main()
{
/*声明结构体,因为是值类型,所以在栈中分配内存*/
SomeVal v1; //有没有分配空间?分配在哪里(堆/栈)? 栈
/*没有初始化,不能运行*/
Console.WriteLine(v1.x); //能运行吗? 不能
/*由于结构体是值类型,所以结构体的实例化可以不使用new运算符。
结构体的new操作不执行分配内存操作,只是执行初始化数据操作
v1还是原来的v1,可尝试输出地址,两者相同*/
v1 = new SomeVal();//有没有分配空间?分配在哪里(堆/栈)? 没有分配空间
/*new SomeVal()不是创造一个对象,而是运行它的默认构造函数,
而构造函数给v1.x赋了初始值,为0*/
Console.WriteLine(v1.x); //输出: 0
/*这里就是正常的变量赋值*/
v1.x = 5;
Console.WriteLine(v1.x); //输出: 5
/*声明类的实例,没有指明内存地址*/
SomeRef r1;//有没有分配空间?分配在哪里(堆/栈)? 没有分配空间
/*这里是因为r1地址不明确*/
Console.WriteLine(r1.x); //能运行吗? 不能
/*动态分配内存,类是引用类型变量,则对象r1分配到堆*/
r1 = new SomeRef();//有没有分配空间?分配在哪里(堆/栈)? 堆
/*默认值是0*/
Console.WriteLine(r1.x); // 输出: 0
/*正常的变量赋值*/
r1.x = 5;
Console.WriteLine(r1.x); // 输出: 5
/*值类型,赋值相当于拷贝一份,在栈区分配了内存*/
SomeVal v2 = v1;
/*引用类型,在栈区分配了内存存放地址,对象仍然指向同一个*/
SomeRef r2 = r1;
/*只改变v1的值,因为v1和v2的对象是不同的*/
v1.x = 9;
/*r1和r2的x都变为了8*/
r1.x = 8;
Console.WriteLine(r1.x); // 输出: 8
Console.WriteLine(r2.x); // 输出: 8
Console.WriteLine(v1.x); // 输出: 9
Console.WriteLine(v2.x); // 输出: 5
/*动态分配内存,类是引用类型变量,则对象sf2_1分配到堆*/
SomeRef2 sf2_1 = new SomeRef2();//sf2_1空间分配在哪里(堆/栈)? 堆
/*值类型作为类的成员变量时,在堆中分配*/
SomeVal sv2_1 = sf2_1.val;//sv2_1空间分配在哪里(堆/栈)? 堆
/*同上*/
SomeRef2 sf2_2 = new SomeRef2();
SomeVal sv2_2 = sf2_2.val;
/*
Equals()方法使用如下:
1) 系统类一般已经覆盖了Equals(),比较的是内容。
值类型和引用类型,Equals()比较的都是内容。
2) 用户自定义类如果没有覆盖Equals(),将调用
父类的Equals (比如是Object),而Object的Equals的比较
是地址(return (this == obj);)
要想让他能够比较两个变量的内容是否相同,那就应该重写Equals方法
但是类SomeRef2中没有重写,且是引用类型。
sf2_1和sf2_2两个地址不同,则输出False
SomeVal是值类型,比较内容,且都是默认值0,则输出True
*/
Console.WriteLine($"两个类实例相等吗?{sf2_1.Equals(sf2_2)}");// 输出: False
Console.WriteLine($"两个结构实例相等吗?{sv2_1.Equals(sv2_2)}");// 输出: True
SomeVal3 sv3_1 = new SomeVal3();
SomeVal3 sv3_2 = new SomeVal3();
/*rf为默认初始值,null*/
Console.WriteLine($"{sv3_1.rf == null} {sv3_2.rf == null}");// 输出: True True
/*引用类型,地址不同,False*/
Console.WriteLine($"两个结构实例相等吗?{sv3_1.Equals(sv3_2)}");// 输出: False
sv3_1.rf = new SomeRef();
sv3_2.rf = new SomeRef();
/*rf是SomeRef类型,依然是引用类型,地址不同,False*/
Console.WriteLine($"两个类实例相等吗?{sv3_1.rf.Equals(sv3_2.rf)}");// 输出: False
}