第八章 理解值和引用
  zOE2xWkB8BXt 2023年11月02日 55 0

8.1 复制值类型的变量和类

*大多数基本数据类型都是值类型,字符串string除外;string是类类型,string实际是System.string的缩写;

*类是引用类型,声明类变量时,编译器分配一小块内存存储类的引用地址,使用new关键字创建类实例时,才在堆中分配一块内存。

*值类型的复制是两个内存块的值都容纳相同的数值,引用类型的复制,复制的只是类的引用地址,两个类变量存储的都是对同一个类对象的引用;

*引用类型的复制与私有数据:类变量的复制只能拷贝类对象的引用,称为浅拷贝;创建两个类实例,使用clone方法能够复制引用的对象,称为深拷贝。

*private关键字创建了不能从类外访问的字段或方法,但并不是说它只能由单个类对象访问,同一个类的不同对象可以互相访问私有数据;私有指的是在类别上的私有,而不是对象上的私有。

*static关键字声明类中的字段为静态字段,所有的类的对象都共享同一个数据。

*使用值类型的参数,将值类型实参传递给方法的行参,方法操作的是对实参的拷贝,对实参原始值无影响

*使用引用类型的参数,将引用类型的实参传递给方法,方法操作的是对实参的拷贝,这个拷贝是对引用类型对象的引用的拷贝,所有的操作都会你映射到引用对象本身。

8.2理解null和可空类型

*变量应在声明时初始化,引用类型的变量可以在初始化时赋值为null,不指向任何引用对象

Circle c = new Circle(42);
Circle cope = null;
copy = c;

*空条件操作符 ?

int ? i = null;
int j = 99;
i = j;//将实参赋值给空变量
j = i//错误

*可空变量i不能作为实参传递

*可空类型有两个属性,hasValue和Value

int ? i = null;
if (!i.hasValue)
{
	i = 99;
}
else
{
	console.Write(i.Value)
}

*可空类型的Value属性是只读的,不可赋值。

8.3 使用ref和out参数

*向方法传递实参时,形参会用实参的拷贝来初始化,不管是值类型、引用类型(会改变引用对象本身的值,但不改为引用其他对象)还是可空类型,方法内部对形参的操作不会影响实参的原始值。

static void Add(int para)
{
	para++;
  Console.Write();
}
static void main()
{
	int i = 42;
  Add(i);//输出43
  Console.Write(i);//输出42
}

*想要实际的修改一个实参,可使用关键字ref和out

*方法的形参前加ref前缀,作为传递的实参前也加ref前缀,作用于参数的所有操作都会作用于实参本身,因为形参和实参引用的是同一个对象

static void Add(ref int para)
{
	para++;
}
static void main()
{
	int i = 42;
  Add(ref i);
  Console.Write(i);//输出43
}

*由方法本身初始化形参,向形参传递为被初始化的实参,可使用out关键字

static void Add(out int para)
{
	para=42;
}
static void main()
{
	int i;//未初始化
  Add(out i);//初始化
  Console.Write(i);//输出42
}

//ref和out关键字,类似于PLC中自定义功能块的输入管脚和输出管脚,必须填写变量,直接更改实参本身。

8.4计算机内存的组织方式

容纳数据的内存分为两个独立的区域,分别是stack栈和heap堆。调用方法时,它的参数和局部变量所需内存从栈中获取,方法结束后(不管是正常结束还是抛出异常),为参数和局部变量分配的内存都会自动归还给栈。这个规则适用于任何代码块中定义的变量,参数和局部变量的声明周期从方法开始时创建,方法结束后消失;所有的值类型都在栈上创建。

使用new关键字创建对象时,构造对象所需的内存从堆中获取,当对象的最后一个引用消失后,对象占用的内存可供重用,但不一定立即回收。堆上创建的对象具有不确定的生命周期。new关键字运行构造器,将堆中的原始内存转换成类对象,将该对象的引用存储到栈中。堆内存是有限的资源,内存耗尽时会抛出OutOfMemryException。

8.5System.Object类

所有的类都是System.Object类的派生类。关键字object是System.Object的别名,用来声明object类型的变量。object类型的变量可以引用任何对象(类或值类型)。

int i = 42;
object o;
o = i;//值类型变量i存储在栈上,o是引用类型,必须引用堆上的对象。实际上运行时在堆上分配一小块内存并将i值拷贝到其中,让o引用该拷贝

8.6装箱:值类型变量i存储在栈上,o是引用类型,必须引用堆上的对象。实际上运行时在堆上分配一小块内存并将i值拷贝到其中,让o引用该拷贝。这种将数据项自动复制到堆上的行为称为装箱。改变变量 i 的原始值,o上所引用的对象不会改变,类似的,修改堆上的值,i 也不会变

强制类型转换:为了访问已装箱的值,必须进行强制类型转换,简称转型。在object对象前加一个圆括号,其中输入类型名称。

int j;
j = (int)o;

8.7拆箱:在转型过程中,编译器发现指定了类型int,会在运行时生成代码检查o实际引用的类型是不是int,如果是则转型成功,提取出值并写入变量 j ,该过程称为拆箱。如果不是,会抛出InvalidCastException。

8.8数据的安全转型

is 操作符:用于验证对象的类型是不是自己希望的,is有两个操作数,左边是对象引用,右边是类型名称。如果左边的对象是右边的类型,则求职结果为true,否则为false。

Circle c = new Circle();
object o = c;
if (o is Circle)
{
 Circle CC = (Circle)o;//转型是安全的
}
else
{
	
}

as操作符:as有两个操作数,左边是对象引用,右边是类型名称。运行时尝试将对象o转换成Circle类型,若成功则返回转型成功的结果,失败则返回null。

Circle c = new Circle();
object o = c;
Circle i = o as Circle;
if (i != null)
{
 //只有转型成功,这里的代码才会执行
}

如果要检查一个object类型的变量是几个类型,可用if或switch语句

o
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
zOE2xWkB8BXt