.Net流水账

C#参数传递,ref、out和params

2018-10-11  本文已影响0人  飞了个鸽_figo

    最近换工作面试,遇到了一个基础的坑,是关于C#参数传递的问题。

    参数传递主要分两种,值传递和引用传递。实际C#还提供的out输出传递和params数组传递,ref和out这两个关键字都能够提供相似的功效,都能实现引用传递。

I. 使用ref传递参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。

II. 使用ref和out时,在方法声明的参数和调用方法时,都要加ref或out关键字。

III. out适用于return多个返回值,而ref用来改变调用者的引用。

params数组传递,提供同一种类型的多参数传递的方案。

1、值传递

(1)值类型

示例代码

---------------Main-----------------

int a=1;

circle(a);

---------------circle-----------------

void circle(int r)

{

r=10;

}

    如下图,值类型存储在栈内存空间上,在被调用方法里修改的是另外一块内存空间的值。

值类型值传递

(2)引用类型

示例代码

---------------Test-----------------

class Test

{

    public int A {get; set;}

}

---------------Main-----------------

var test=new Test();

test.A=1;

Set(test);

---------------Set1-----------------

void Set(Test t)

{

    t.A=10;

}

    如下图,test和t两个变量指向的是同一个实例,所以当t去修改A属性的时候,实际上是修改了test指向的实例。

引用类型值传递

---------------Set2-----------------

void Set(Test t)

{

    t=new Test();

    t.A=10;

}

    这种情况需要注意,一开始test和t都指向同一个实例。在Set方法内部对t重新分配另外一块内存空间,接下来t的任何操作都在另外一块内存空间上,跟test没有关系。

引用类型值传递

2、引用传递

(1)值类型

示例代码

---------------Main-----------------

int a=1;

circle(ref a);

---------------circle-----------------

void circle(ref int r)

{

    r=10;

}

    实际上,a和r指向的是同一块内存空间,r修改了,实际上就是修改了a。

值类型的引用传递

(2)引用类型

示例代码

---------------Test-----------------

class Test

{

public int A {get; set;}

}

---------------Main-----------------

var test=new Test();

test.A=1;

Set(ref test);

---------------Set1-----------------

void Set(ref Test t)

{

    t=new Test();

    t.A=10;

}

    test传入的是指针,所以当指针指向另外一个实例时,t和test指向的就是该指针指向的实例,它们操作的都是这个实例对应的内存。

引用类型引用传递

总结

(1)C#的值类型存储在栈上,引用类型却存储在CLR托管堆中。

(2)ref传递的是参数的引用。

上一篇下一篇

猜你喜欢

热点阅读