前言:在c#中,所有的数据类型都可以称为“对象”,因为所有数据类型都是一个封装好的类。这一点与c/c++不同。
- 为什么这么说呢?看代码:
int i = int.MaxValue;//取int的类型的最大值给i
1.值类型和引用类型:
我们所学的值类型和引用类型究竟是什么:
- 值类型:基本数据类型:(int , bool , double ,float ,byte,short ,long)(struct enum)等。
- 其中一些基本类型的字节如下:
- byte:1 字节;
- bool:(true false)
- int :4 字节
- short:2字节
- long:8字节
- 引用类型:(类,接口,委托等)
2.值类型特殊情况:
2-1.不能大字节变量赋值给小字节变量,可以小字节赋给大字节。(bool类型不能赋值给其他值。)
int i = 1; short b = i;//也不能在声明的时候进行隐式转换
如上代码:报错。
原因:当我们不同类型进行赋值的时候会出现隐式转换的现象。上面所说因为我们的数据类型都是一个类。相当于我们变量名赋值的话会出现“隐式转换的拷贝构造”,也就是说隐式转换是需要所有属性都相同才能赋值,否则不行。
很明显,我们的int占用4个字节,里面的属性肯定很多,和short的属性不相匹配因此无法转换。如果我们非要转换可以使用强制转换,或者as语法。如下代码:
int i = 1; short b; b = (short)i;
2-2.值类型一般也会产生装箱拆箱的操作:
装箱:把值类型copy,丢到内存堆里面去,装入转换成object类型
int i = 0; object o = i;
拆箱:把object类型转换为值类型
int b = (int) o ;
2-3.值类型变量相互赋值的时候,是copy副本来赋值的。
1.也就是说值类型是,把10的值copy一份给了b,而不是把a的地址引用给b,b改变值,a不会变。
int a = 10; int b = a;
2-4值类型的存储地址是在栈区。
栈区的特点:先进后出。
2-5值类型会被系统自动回收内存。
2-6值类型一般都会运行比较快。
特殊点:struct
当struct中存在着引用类型的时候,struct的变量不是变成了另一个变量的引用。
例子如下:虽然唯一哈希值是一样的。但是本质地址是不一样的,所以num地址也是不一样的。两个不同的对象可能具有相同的哈希值。这种情况被称为哈希碰撞。哈希算法设计目的是尽量避免哈希碰撞,但无法完全避免。
public class Score { public int Chinese { get; set; } public int Math { get; set; } public int English { get; set; } } internal class Program { public struct Student { public Score score; public int num; } static void Main(string[] args) { Student s; s.score = new Score(); s.num = 0; Student S1 = s; S1.score.Chinese = 100; S1.num = 1000; Console.WriteLine("S1 的语文成绩是:" + " num is " + S1.num); Console.WriteLine("s 的语文成绩是:" + " num is " + s.num); Console.WriteLine("S1 的语文成绩是:" +" num is " + S1.GetHashCode()); Console.WriteLine("s 的语文成绩是:" + " num is " + s.GetHashCode()); Console.WriteLine(Object.ReferenceEquals(s,S1)); Console.ReadLine(); } }
运行结果:
但是呢,结构体里面若是有引用对象的话,这是里面的成员会引用同一个空间:根据上面代码改动:
namespace Test0 { public class Score { public int Chinese { get; set; } public int Math { get; set; } public int English { get; set; } } internal class Program { public struct Student { public Score score; public int num; } static void Main(string[] args) { Student s; s.score = new Score(); s.num = 0; Student S1 = s; S1.score.Chinese = 100; S1.num = 1000; Console.WriteLine("S1 的语文成绩是:" + " num is " + S1.num); Console.WriteLine("s 的语文成绩是:" + " num is " + s.num); Console.WriteLine("S1 的语文成绩是:" +" num is " + S1.GetHashCode()); Console.WriteLine("s 的语文成绩是:" + " num is " + s.GetHashCode()); Console.WriteLine(Object.ReferenceEquals(s.score,S1.score)); Console.ReadLine(); } } }
运行结果:
我们说字符串也是一个引用类型,假如我们把成员的引用类型换成字符串呢?
namespace Test0 { public class Score { public int Chinese { get; set; } public int Math { get; set; } public int English { get; set; } } internal class Program { public struct Student { public String score; public int num; } static void Main(string[] args) { Student s; s.score = "100000000"; s.num = 0; Student S1 = s; S1.score = "99999999"; S1.num = 1000; Console.WriteLine("S1 的语文成绩是:" + " num is " + S1.num); Console.WriteLine("s 的语文成绩是:" + " num is " + s.num); Console.WriteLine("S1 的语文成绩是:" +" num is " + S1.GetHashCode()); Console.WriteLine("s 的语文成绩是:" + " num is " + s.GetHashCode()); Console.WriteLine(Object.ReferenceEquals(s.score,S1.score)); Console.ReadLine(); } } }
运行结果:
为什么明明这是引用类型,而不是同一个地址呢?
工作繁忙,我们下期分享。
------------------------------------------------------------------------------------------------------------------
感谢收看!!!