HTML5技术

你必须知道的C#.Net参数知识大盘点 - 陌城心灵捕手(4)

字号+ 作者:H5之家 来源:H5之家 2016-09-03 11:00 我要评论( )

在进行参数的引用传递时,当传递的参数为引用类型时,实际上传递的是该引用类型实例的引用的引用(不是实例引用的副本)。 因此方法操作的是引用类型实例的引用的引用,在方法中对参数所做的任何更改都将反映在该变

在进行参数的引用传递时,当传递的参数为引用类型时,实际上传递的是该引用类型实例的引用的引用(不是实例引用的副本)。
因此方法操作的是引用类型实例的引用的引用,在方法中对参数所做的任何更改都将反映在该变量中。

ChangeValue(ref string value) { /* value的引用 * value的引用的引用 * value的引用指向对象实例,而[value的引用的引用]指向[value的引用] * 所以其本质就是修改value的引用所指向的托管堆里的内存块里面的值 */ value = ; } Main() { ; //实际上传递的是value实例的引用的引用(类似于指针的指针) ChangeValue(ref value); //由于ChangeValue方法修改了value的引用的引用所指向的内存块里面的值,所以输出是:“update” Console.WriteLine(value); }

由于C#指针只能用来操作值类型,所以上面只有值类型对象的指针操作的屏幕演示gif动画,就当锦上添花加深理解吧。
既然指针已经过来凑热闹了,我就多说一句,C#指针和引用的确类似,但是还是有所区别,是两个不同的概念。

讲解到这里的时候,我们基本上在脑海中已经开始有一些结论了:
值类型的值传递:  实际传的就是实例的 副本。
引用类型的值传递: 实际传的就是实例的 引用的副本。
值类型的引用传递: 实际传的就是实例的 引用。
引用类型的引用传递:实际传的就是实例的 引用的引用。
在C#中,必须使用ref或者out参数修饰符显式声明的情况下,参数才会按照引用传递,否则默认就是按照值传递。
不管使用了什么障眼法,或者代码绕了什么弯,只要抓住其本质,都可以把赋值操作和内存分布及其地址指向说的清清楚楚。 

 

ref引用参数/out输出参数   参数修饰符

如果方法签名中的参数使用了ref、out修饰符,那么就是显式的告诉编译器,该参数是按照引用传递。我们不妨看看IL代码,就一目了然了,如下图所示:


通过上图可以看出,在调用带有ref、out参数修饰符的方法时,传递参数时都会加上&运算符。

看看IL代码,顺便对比一下加了ref之后是什么样子:

ChangeValue(int value) { value = 0; } ChangeValue(ref int value) { value = 0; } Main() { int a = 1; ChangeValue(a); ChangeValue(ref a); } //以下是IL代码 .method private hidebysig static void Main () cil managed { // Method begins at RVA 0x2350 // Code size 16 (0x10) .maxstack 1 .entrypoint .locals init ( [0] int32 a ) IL_0000: ldc.i4.IL_0001: stloc.IL_0002: ldloc.IL_0003: call void ConsoleTest.Program::ChangeValue(int32) IL_0008: ldloca.s a //将局部变量a的地址加载到堆栈上。 【这个地方走ChangeValue(ref a),则是把堆栈上的地址拿过来。由此可见,加上ref修饰符之后,传的就是实例的引用地址了】 IL_000a: call void ConsoleTest.Program::ChangeValue(int32&) //注意看这地方多了&运算符 IL_000f: ret } // end of method Program::Main

 

传递到ref形参的实参必须先经过初始化,然后才能传递,out则不需要。
属性或索引器不能作为 out 或 ref 参数传递,因为它们的本质是方法,而不是变量。
ref或者out可以实现方法重载,但是不能同时实现方法重载。例如void Test(ref int a)和void Test(out int a)同时出现并实现方法重载则会编译报错。

 

泛型类型参数

在泛型类型或方法定义中,类型参数是客户端在实例化泛型类型的变量时指定的特定类型的占位符。客户端代码必须通过指定尖括号中的类型参数来声明和实例化构造类型。此特定类的类型参数可以是编译器识别的任何类型。可以创建任意数目的构造类型实例,每个实例使用不同的类型参数。尖括号中出现的每个 T 都会在运行时替换为相应的类型参数。通过这种替换方式,我们可以使用一个泛型定义并创建多个独立的类型安全的有效对象。

泛型类型参数的约束

 

约束

说明

where T: struct

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。

where T: class

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 前端必须要掌握的几个CSS3的属性 - 丶小卒

    前端必须要掌握的几个CSS3的属性 - 丶小卒

    2016-07-13 16:00

  • 学习ASP.NET Core,你必须了解无处不在的依赖注入 - Artech

    学习ASP.NET Core,你必须了解无处不在的依赖注入 - Artech

    2016-07-06 10:00

  • 你可能不知道的7个CSS单位 - jerrylsxu

    你可能不知道的7个CSS单位 - jerrylsxu

    2016-05-27 12:04

  • 如果你已经这样了,那你必须要跳槽了。 - 左潇龙

    如果你已经这样了,那你必须要跳槽了。 - 左潇龙

    2016-02-01 08:06

网友点评
d