c# ref关键字对于引用类型传递的影响
我们可能见到下面的代码
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关键字对于引用类型传递的影响的更多相关文章
- .net ref关键字在引用类型上的使用
只接上干货. namespace ConsoleApplication1 { class Person { public string UserName { get; set; } } class P ...
- ref 关键字修饰引用类型
对于再分配引用对象的引用的操作,没有Ref修饰时是不能在外部生效的,只有有Ref修饰的引用参数才能使再分配操作应用于外部 侵删.
- C#中引用类型的变量做为参数在方法调用时加不加 ref 关键字的不同之处
一直以为对于引用类型做为参数在方法调用时加不加 ref 关键字是没有区别的.但是今天一调试踪了一下变量内存情况才发现大有不同. 直接上代码,结论是:以下代码是使用了 ref 关键字的版本.它输出1 ...
- ref 关键字out关键字
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- C#基础:值类型、引用类型与ref关键字
在C#中,ref的意思是按引用传递.可以参考C++: int a = 10, b = 20; void swap(int x, int y) { int temp = x; x = y; y = te ...
- C#中 ref 关键字的认识和理解
之前接手老项目的时候有遇到一些的方法参数中使用了ref关键字加在传参的参数前面的情况.对于新手,这里介绍和讲解一下ref的用法和实际效果. CLR中默认所有方法的参数传递方式都是传值,也就是说不管你传 ...
- c#基础语言编程-按值类型和引用类型传递参数
引言 在介绍传递参数介绍前,请明白参数类型和传递方式是不同的.传递方式分为按值类型和引用类型传递参数.参数类型有值类型和引用类型,这个和C++是不同的.这里的传递方式对应c++中的深复制和浅复制. 两 ...
- 《ASP.NET 1200例》ref关键字与out关键字
REF关键字 ref 关键字会导致通过引用传递的参数,而不是值. 通过引用传递的效果是在方法中对参数的任何改变都会反映在调用方的基础参数中. 引用参数的值与基础参数变量的值始终是一样的. 不要将“通过 ...
- C#:ref关键字和out关键字的区别
1.在不使用关键字(比如ref关键字.out关键字等)修饰函数的情况下,大部分函数的参数是以值传递的方式,也就是说,“调用函数”在使用参数(比如myNumber)时,是把该参数复制多一份,然后将其传递 ...
随机推荐
- linux 安装软件,卸载软件 等的几种方式
安装软件的步骤和基本原则: 1. rpm安装: 定义: rpm是由红帽公司开发的软件包管理方式,使用rpm我们可以方便的进行软件的安装.查询.卸载.升级等工作.但是rpm软件包之间的依赖性问题往往会很 ...
- Learn clojure in Y minutes
Learn X in Y minutes Where X=clojure Get the code: learnclojure.clj Clojure is a Lisp family languag ...
- oracle数据库常用SQL语句(11.29更新)
笔者日常工作中常用到的sql语句,现总结如下,留作日后查看. 1.按照两列中的最大值取 ,只取两列其中的一列 SELECT * FROM t_doc T ORDER BY GREATEST(T.Loa ...
- URAL 1158 AC自动机上的简单DP+大数
题目大意 在一种语言中的字母表中有N(N<=50)个字母,每个单词都由M(M<=50)个字母构成,因此,一共可以形成N^M个单词.但是有P(P<=10)个串是被禁止的,也就是说,任何 ...
- FFT快速傅立叶变换的工作原理
实数DFT,复数DFT,FFTFFT是计算DFT的快速算法,但是它是基于复数的,所以计算实数DFT的时候需要将其转换为复数的格式,下图展示了实数DFT和虚数DFT的情况,实数DFT将时域中N点信号转换 ...
- 大嫂的HTML
<html> <head> <style type="text/css"> *{ margin: 0; padding: 0; ...
- String性能优化
String 使用的优化建议 其他 String 使用的优化建议 以上我们描述了在我们的大量文本分析案例中调用 String 的 subString方法导致内存消耗的问题,下面再列举一些其他将导致内存 ...
- hdu2795 线段树
//Accepted 6396 KB 3046 ms //线段树 //由于n只有200000,我们可以知道,当h>200000时,大于200000的部分是没有用的 //所以我们可以用n来创建线段 ...
- 全球著名的渗透测试Linux简介
注:如发现链接无法打开,请尝试代理登录链接 1. Kali Linux Kali Linux是基于Debian的Linux发行版, 设计用于数字取证和渗透测试.由Offensive Security ...
- C杂记
printf主要是为了便于取地址,默认将char,short变成了int,float变成了double:但scanf的时候,因为数据宽度的问题,必须区分%f和%lf. memset 是字符串操作函数: ...