我们可能见到下面的代码

public static void StringBuilderNoRef(StringBuilder s)     {

s.Append(" World");

s = new StringBuilder("hi");

}

public static void StringBuilderRef(ref StringBuilder s)     {

s.Append(" World");

s = new StringBuilder("hi");

}

当我们先创建一个实例 StringBuilder s = new StringBuilder("Hello");

把s作为参数分别传递到两个方法的时候,我们会发现

输出结果是不一样的,一个是 Hello World,另一个是 hi

原因其实就是 在调用第一个方法的时候,传递了这个引用类型对象的引用的副本(不是对象本身),所以对于在调用方法外部的引用和方法中的引用来说,这两个引用都指向堆上的同一个对象。所以在修改此对象的属性值时,修改同时会应用于内部和外部的两个引用上。但重新分配其引用位置时,则只是修改副本引用的引用位置,原引用(方法外部)的位置不变,原引用还是指向原来的对象。
而如果加上Ref关键字,这时传入的参数则为些引用对象的原始引用,而不是引用的副本,这样的话,你就不但可以修改原始引用对象的内容,还可以再分配此引用的引用位置(用New 来重新初始化)。
如果你只想在方法中改变引用参数的内容,没有必要使用Ref来修饰引用参数。
如果你希望在方法中改变引用对象参数的引用(调用方法外的),如重新初始化对象,则需要使用Ref关键字来修饰参数。

下面我们再结合下图,阐述一下我理解的 实例 引用 对象 副本的区别和联系

  如图,new Person()是真正的对象是在堆内存里面,上图一共有3次new Person(),所以会在堆里面开辟3个空间,产生3个实例对象,每个对象之间都是相互独立的,使用自己的空间。而new Person()就是一个实例化的过程,将类Person生产出不同的对象。

  而等号的左边$p1是一个引用变量,通过赋值运算符“=”把对象的首地址赋给“$p1“这个引用变量,
所以$p1是存储对象首地址的变量,$p1放在栈内存里边,$p1相当于一个指针指向堆里面的对象, 所以我们可以通过$p1这个引用变量来操作对象,
通常我们也称对象引用为对象。

  其实一个对象就是一个实例,而引用是指一个存放对应首地址的对象,通过$p1这个引用变量来操作对象。

  副本则是拷贝了该引用的指针。

c# ref关键字对于引用类型传递的影响的更多相关文章

  1. .net ref关键字在引用类型上的使用

    只接上干货. namespace ConsoleApplication1 { class Person { public string UserName { get; set; } } class P ...

  2. ref 关键字修饰引用类型

    对于再分配引用对象的引用的操作,没有Ref修饰时是不能在外部生效的,只有有Ref修饰的引用参数才能使再分配操作应用于外部 侵删.

  3. C#中引用类型的变量做为参数在方法调用时加不加 ref 关键字的不同之处

    ​ 一直以为对于引用类型做为参数在方法调用时加不加 ref 关键字是没有区别的.但是今天一调试踪了一下变量内存情况才发现大有不同. 直接上代码,结论是:以下代码是使用了 ref 关键字的版本.它输出1 ...

  4. ref 关键字out关键字

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  5. C#基础:值类型、引用类型与ref关键字

    在C#中,ref的意思是按引用传递.可以参考C++: int a = 10, b = 20; void swap(int x, int y) { int temp = x; x = y; y = te ...

  6. C#中 ref 关键字的认识和理解

    之前接手老项目的时候有遇到一些的方法参数中使用了ref关键字加在传参的参数前面的情况.对于新手,这里介绍和讲解一下ref的用法和实际效果. CLR中默认所有方法的参数传递方式都是传值,也就是说不管你传 ...

  7. c#基础语言编程-按值类型和引用类型传递参数

    引言 在介绍传递参数介绍前,请明白参数类型和传递方式是不同的.传递方式分为按值类型和引用类型传递参数.参数类型有值类型和引用类型,这个和C++是不同的.这里的传递方式对应c++中的深复制和浅复制. 两 ...

  8. 《ASP.NET 1200例》ref关键字与out关键字

    REF关键字 ref 关键字会导致通过引用传递的参数,而不是值. 通过引用传递的效果是在方法中对参数的任何改变都会反映在调用方的基础参数中. 引用参数的值与基础参数变量的值始终是一样的. 不要将“通过 ...

  9. C#:ref关键字和out关键字的区别

    1.在不使用关键字(比如ref关键字.out关键字等)修饰函数的情况下,大部分函数的参数是以值传递的方式,也就是说,“调用函数”在使用参数(比如myNumber)时,是把该参数复制多一份,然后将其传递 ...

随机推荐

  1. qml的打包问题

    qml2的打包问题: 相对于早期的项目,只需要打包plugin和动态库.带有sqlite的程序如果需要打包,需要打包如下东西: 1.打包AppData目录下的  Local/Qt Project/项目 ...

  2. soap

    sudo apt-get update apt-get install php-soapphp-config --configure-options --enable-soap php -i | gr ...

  3. Section 1.4 Mother's Milk

    又是一道怨念已久的题目0 0之前深搜写过广搜写过,怎么就是卡死,我还以为FP坏了重新装了一遍.今天偶尔翻起来,发现广搜忘记inc(head)了…简直哭瞎… 简单的广搜,分类比较多,不过不太要动脑子.至 ...

  4. io函数

    io函数一般分为两大类: 系统(不带缓存)调用: 如read.write.open 标准(带缓存)调用: fread.fwrite.fopen 上面说的带缓存/不带缓存是针对用户态的,内核态本身都是带 ...

  5. 基于百度定位及天气获取的DEMO

    demo基于百度定位APIv4.0版.新浪天气(不用查询城市代码). 需求: 1.button实现触发定位监听和天气捕获 2.两个textview 分别显示详细地址.天气. 界面很简陋,侧重功能实现. ...

  6. C/C++学习之基础-001

    1.C++虚函数的工作原理 虚函数(virtual function)需要虚函数表(virtual table)才能实现.如果一个类有函数声明成虚拟的,就会生成一个虚函数表,存放这个类的虚函数地址.若 ...

  7. 红帽中出现”This system is not registered with RHN”的解决方案

    原因是你的linux没有在红帽网络上注册,所以无法下载上面的软件包,替代方案可以使用centos. 下面介绍下使用centos 的流程 1.卸载rhel的默认安装的yum包查看yum包rpm -qa| ...

  8. EF学习笔记(一)

    EF(EntityFramwork)实体框架:主要是将实体类(EntityClass)和数据表(Table)进行映射(Map). EF核心对象: DbContext   (数据访问核心对象)      ...

  9. 5月18日:top10面试算法-LRUcache的实现

    问题描述: LRU算法:优先把那些最长时间没使用的对象置换掉.根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”. JAVA实现: 测试: publ ...

  10. 基于HTML5+CSS3的图片旋转、无限滚动、文字跳动特效

    本文分享几种基于HTML5+CSS3实现的一些动画特效:图片旋转.无限滚动.文字跳动;实现起来均比较容易,动手来试试! 一.图片旋转 效果图如下: 这个效果实现起来其实并不困难.代码清单如下: < ...