String是引用类型
关于String为值类型还是引用类型的讨论一直没有平息,最近一直在研究性能方面的问题,今天再次将此问题进行一次明确。希望能给大家带来点帮助。 如果有错误请指出。
来看下面例子:
//值类型
int a = ;
int b = a;
a = ;
Console.WriteLine("a is {0},b is {1}", a, b); //字符串
string str1 = "ab";
string str2 = str1;
str1 = "abc";
Console.WriteLine("str1 is {0},str2 is {1}", str1, str2);
Console.Read();
根据上面的例子:你觉得输出结果应该是什么?
输出结果:
//结果:
//a is 2,b is 1
//str1 is abc,str2 is ab
str2依然是ab,并没有随str1的改变而改变。
str2依然是ab,并没有随str1的改变而改变。
如果string是引用类型,按理Str1和Str指针都指向同一内存地址,如果Str的内容发生改变,Str1应该也会相应变化。
此例子,看着string更像是值类型。
但是MSDN却说String是引用类型,
string对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了,实际是string经过了特殊处理,每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因,如果经常改变string的值则应该使用StringBuilder而不使用string
引用类型包括:
String
所有数组,即使其元素是值类型
类类型,如 Form
委托
可参考:http://msdn.microsoft.com/zh-cn/library/t63sy5hs(VS.80).aspx
查看具体引用是否相同
如果Net能够查看内存地址就容易了,但不允许,只能通过间接方法来实现,看下面:
static void TestRefAddress()
{
String str1 = "abc";
String str2 = "abc";
int a = ;
int b = ;
StringBuilder strb1 = new StringBuilder("abc");
StringBuilder strb2 = new StringBuilder("abc");
Console.WriteLine("Reference equal for string: " + Object.ReferenceEquals(str1, str2)); //结果true
Console.WriteLine("Reference equal for int: " + Object.ReferenceEquals(a, b)); //结果false
Console.WriteLine("Reference equal for StringBuilder: " + Object.ReferenceEquals(strb1, strb2)); //结果false
Console.WriteLine("Value equal for string: " + str1.Equals(str2)); //结果true,类似于值类型
Console.Read();
}
结果为何出现如此情况,分析如下:
Console.WriteLine("Reference equal for string: " + Object.ReferenceEquals(str1, str2)); //结果true,不同对象,但引用地址相同
Console.WriteLine("Reference equal for int: " + Object.ReferenceEquals(a, b)); //结果false,值类型装箱操作造成
Console.WriteLine("Reference equal for StringBuilder: " + Object.ReferenceEquals(strb1, strb2)); //结果false,不同对象,引用地址不同
Console.WriteLine("Value equal for string: " + str1.Equals(str2)); //结果true,类似于值类型
由第一条结果,可以判定不同的String的,相同的值,其引用地址相同,再由第四条结果,str1.Equals(str2),两者结合,可得出结论,两个String,如果赋值为同一个值,在内存中只有一个字符串存在,两个引用的地址相同。由此引出String的不变性。
String的不变性
string最为显著的一个特点就是它具有恒定不变性:我们一旦创建了一个string,在managed heap 上为他分配了一块连续的内存空间,我们将不能以任何方式对这个string进行修改使之变长、变短、改变格式。所有对这个string进行各项操作(比如调用ToUpper获得大写格式的string)而返回的string,实际上另一个重新创建的string,其本身并不会产生任何变化。
string 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。有的时候看来似乎修改了,实际是string经过了特殊处理,每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因。
String的不变,并非说string不能改变,而是其值不能改变。
在例子中str1="ab",这时在内存中就将“ab”存下来,如果再创建字符串对象,其值也等于“ab”,str2="ab",则并非再重新分配内存空间,而是将之前保存的“ab”的地址赋给str2的引用,这就能印证例子2中的结果。而当str1="abc"其值发生改变时,这时检查内存,发现不存在此字符串,则重新分配内存空间,存储“abc”,并将其地址赋给str1,而str2依然指向“ab”的地址。可以印证例子1中的结果。
结论:
String是引用类型,只是编译器对其做了特殊处理。
String是引用类型的更多相关文章
- .net中String是引用类型还是值类型 以及 C#深层拷贝浅层拷贝
http://www.cnblogs.com/yank/archive/2011/10/24/2204145.html http://www.cnblogs.com/zwq194/archive/20 ...
- [No0000B4].Net中String是引用类型还是值类型,答string是特殊的引用类型
using System; internal class Program { private static void Main() { //值类型 ; int b = a; a = ; Console ...
- 课堂随笔02--c#中string作为引用类型的特殊性
using System; namespace Test { class Test1 { static void Main(string[] args) { string str1 = "1 ...
- 为什么string是引用类型 值还不可以修改
C#把数据类型分为值类型和引用类型.值类型操作简单,引用类型更省空间. C#一共有15个预定义类型,其中13个值类型(8个整型.2个浮点类型.decimal.bool.char),2个引用类型(str ...
- string引用类型解惑
先上代码: string b = "123"; private void Form1_Load(object sender, EventArgs e) { Test(b); Mes ...
- String属于“假引用类型”,代码为证(一个String引发的血案...)
一直以为String是引用类型,今天写了个浅拷贝的测试,发现String有基本类型的特征. class A{ public int a = 555; } class User implements C ...
- String为值类型还是引用类型
关于String为值类型还是引用类型的讨论一直没有平息,最近一直在研究性能方面的问题,今天再次将此问题进行一次明确.希望能给大家带来点帮助. 如果有错误请指出. 来看下面例子: //值类型 int a ...
- C#中string类型是值类型还是引用类型?
.Net框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一个引用类型,也就是说线程上的堆栈上不会驻留有任何字符串. string类型(引用类型) 名称 CT ...
- C#中string类型是值类型还是引用类型?(转)
出处:https://www.cnblogs.com/dxxzst/p/8488567.html .Net框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一 ...
随机推荐
- java设计优化--观察者模式
观察者模式介绍 观察者模式是一种非常有用的设计模式,在软件系统中,当一个对象的行为依赖于另一个对象的状态时,观察者模式就非常有用.如果不适用观察者模式,而实现类似的功能,可能就需要另外启动一个线程不停 ...
- Linux安装卸载JDK(1.7 rpm)
一.卸载系统已有的JDK 1.查看已安装的jdk rpm -qa|grep jdk 2.卸载jdk rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.66. ...
- Oracle数据库语句大全
转自:http://blog.sina.com.cn/s/blog_b5d14e2a0101c56z.html ORACLE支持五种类型的完整性约束 NOT NULL (非空)--防止NULL值进入指 ...
- BZOJ-3231 递归数列 矩阵连乘+快速幂
题不是很难,但是啊,人很傻啊...机子也很鬼畜啊... 3231: [Sdoi2008]递归数列 Time Limit: 1 Sec Memory Limit: 256 MB Submit: 569 ...
- hihocoder #1270 建造基地
传送门 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在遥远的未来,小Hi成为了地球联邦外空间联合开发工作组的一员,前往一颗新发现的星球开发当地的重金属资源. 为了能够 ...
- Dinic 算法
#include <bits/stdc++.h> using namespace std; ), M(1e5+); int head[N]; struct Edge{ /* r: resi ...
- IOS 面试
1. #import , #include的区别 @import防止类的重复引用,#import 确定一个文件只能被导入一次,这使在递归包含中不会出现问题. @class一般用于头文件中需要声明该类的 ...
- automapper初步
首先引入 automapper.dll using System; using System.Collections.Generic; using System.Linq; using System. ...
- 在多浏览器使用JS复制内容到剪切板,无需插件
最近在学习DHTMLX,下载了一些JS源码,使用谷歌浏览器,在学习dhtmlxGrid部分进行复制表格内容时,发现,在线版的可以复制成功,而本地的不可以复制,报类似访问剪切板错误,经查找原因,原来是谷 ...
- VS2010+OpenCV2.4.6永久性配置方法
1. 配置OpenCV环境变量 计算机->(右键)属性,出现如图1所示界面 单击“高级系统设置”,选中高级(标签)出现如图2所示界面 单击右下方的“环境变量”,弹出如图3所示界面,注意这里最好用 ...