一、示例演示

namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""); List<string> list1 = new List<string>();
Test1(list1);
Console.WriteLine(" list1:" + list1.Count()); // 总数量为 1 Console.WriteLine("");
Console.WriteLine("---- 亮瞎眼的分割线 ----");
Console.WriteLine(""); List<string> list2 = new List<string>();
Test2(list2);
Console.WriteLine(" list2:" + list2.Count()); // 总数量仍为 0 Console.WriteLine("");
} static void Test1(List<string> list)
{
list.Add("");
Console.WriteLine(" Test1():" + list.Count()); // 总数量为 1
} static void Test2(List<string> list)
{
List<string> list2 = new List<string>();
list2.Add(""); list = list2;
Console.WriteLine(" Test2():" + list.Count()); // 总数量为 1
}
}

可以发现:

经过 Test1后,list 的元素数量由 0 变为 1 了,

经过 Test2后,list 的元素数量还是0。

二、解说

1.list类型是引用类型

2.引用本身是类似于一个“保存地址的值变量”
所以从方法外部传入引用到方法里,那么其实引用本身是复制了一份副本来给方法里使用的,只是说这个复制的引用副本和之前的引用的内容(也就是所指向的对象内存地址)是一样的,所以通过引用操作对象的数据时,可以看到2个引用都操作的同一个对象;但如果你是修改了引用副本本身的值内容(将该引用指向了一个新的对象的内存地址),那么是不会影响到之前方法外的那个引用的,所以修改后会发现2个引用所指向的对象不同了

而如果对象引用参数前加上了ref,那么方法参数所传递的不再是引用的副本,而是引用的地址了(即通过引用的地址找到引用,再读出引用里保存的内存地址值,再根据则个地址值去找到真正要操作的对象),所以如果此时你再修改这个引用的值时,会根据引用的地址找到方法外的那个引用,然后修改其内容,所以会发现方法外的引用也会指向新的对象了

3这里有三段代码

你可以看看,体会一下:

(1)

List<string> list=new List<string>();
ModifyList(list);
Console.WriteLine(list.Count) private void ModifyList(List<string> list)
{
// 这里的list其实已经是一个引用副本了,但是所指向的内存地址仍然是原本方法外面的对象的,所以后面用该引用的Add方法所操作的,仍然是原本方法外面的对象的内存数据
list.Add("");
list.Add("");
list.Add("");
}

(2)

List<string> list=new List<string>();
ModifyList(list);
Console.WriteLine(list.Count) private void ModifyList(List<string> list)
{
list = new List<string>(); // 这里其实已经将引用指向了新的内存地址,所以后续的Add操作是在操作新对象的内存数据,而原来方法外的对象其实是没有受到影响的
list.Add("");
list.Add("");
list.Add("");
}

(3)

List<string> list=new List<string>();
List<string> copy = list; // 复制一个引用
ModifyList(ref list);
Console.WriteLine(copy.Count) // 复制的这个引用仍然指向原来最早的那个List
Console.WriteLine(list.Count) // list这个引用已经在ModifyList方法里被修改了,指向的是在ModifyList方法里新new出来的对象了 private void ModifyList(ref List<string> list)
{
list = new List<string>(); // 因为有ref,所以这里其实已经将方法外原本的那个引用也指向了新的内存地址,所以后续的Add操作是在操作新对象的内存数据,并且方法外原本的那个引用也指向了这个新的对象
list.Add("");
list.Add("");
list.Add("");
}

参考:

http://www.cftea.com/c/2013/01/5724.asp

http://bbs.csdn.net/topics/390600826

最新文章

  1. samba服务配置
  2. UESTC 1851 Kings on a Chessboard
  3. POJ3461Oulipo 题解
  4. ACM题目————网格动物
  5. D3D 模板缓存的创建过程
  6. SetWindowHookEx 做消息响应
  7. iOS - PassData
  8. HTML/CSS的学习过程一览
  9. Linux 修改swap虚拟内存大小
  10. Android 上拉加载更多功能
  11. iOS 开发 NSLog调试小技巧
  12. 王灏:光音网络致力打造Wi-Fi大生态圈
  13. 在浏览器中简单输入一个网址,解密其后发生的一切(http请求的详细过程)
  14. 编写可维护的javascript代码--- 2015.11.22(注释)
  15. 扩展方法where方法查询不到数据,不会抛异常,也不是返回的null
  16. HDU5477(模拟)
  17. Linux基本命令整理_sheng
  18. vue调试工具vue-devtools安装及使用
  19. Java代码输出是“father”还是“child”(二)
  20. 原生Js操作DOM

热门文章

  1. springcloud 服务调用的两种方式
  2. Mysql查看表的建表语句
  3. 委托(Delegate)简介
  4. [Android] Android 使用 Greendao 操作 db sqlite(2)-- 封装DaoUtils类
  5. 启动aspx文件错误
  6. Web服务常见问题
  7. 大规模数据导入和导出(oracle)
  8. python 小技巧
  9. (6)设计一个TimeMap
  10. flex中使用white-space