我们可能见到下面的代码

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. java语句类型

    public class Test { public static void main(String[] args) { System.out.println("Test is ok&quo ...

  2. hdu 4638 Group

    http://acm.hdu.edu.cn/showproblem.php?pid=4638 问题其实就是求[L,R]中有多少个连续的段 若每一个人都是一个段 那么[L,R]中每一个朋友关系就会减少一 ...

  3. python 操作json

    认识 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - Dece ...

  4. 第一次使用Git心得体会

    用书本上的概念讲,Git是一个分布式的版本控制工具,每一个Git的工作目录都是一个完全独立的代码库,并拥有完整的历史记录和版本追踪能力,能够不依赖于网络和中心服务器.也就是说Git能够不需要服务器而在 ...

  5. HDU 1203-Program D

    Description Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了.要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的 ...

  6. Android Studio 配置JPush

    1.在JPush官方下载 JPush SDK(jpush-android-arm-2.1.0.zip),我下载的是2.1.0: 2.解压下载好的压缩包(jpush-android-arm-2.1.0. ...

  7. android 获取activity 的name

    String contextString = this.toString();String name = contextString.substring(contextString.lastIndex ...

  8. MapReduce数据流(二)

    输入块(InputSplit):一个输入块描述了构成MapReduce程序中单个map任务的一个单元.把一个MapReduce程序应用到一个数据集上,即是指一个作业,会由几个(也可能几百个)任务组成. ...

  9. Android获取手机设备识别码(IMEI)和手机号码

    最近看了下获取手机设备ID和手机信息以及SIM的信息例子,主要还是借鉴别人的,现在自己写一下,算是巩固加深了,也希望能给大家一个参考 必要的条件还是一部真机,SIM卡或者UIM卡. 首先,在Andro ...

  10. Python开发入门与实战1-开发环境

    1.搭建Python Django开发环境 1.1.Python运行环境安装 Python官网:http://www.python.org/ Python最新源码,二进制文档,新闻资讯等可以在Pyth ...