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,这使得它成为一 ...
随机推荐
- RAID 磁盘状态为foreign,怎么变成ready
我们在关掉电源,插入三块硬盘,打开电源 这时候: 首先启动服务器,出现[Press<ctrl><R>to Run Configuration Utility]提示时,按下ctr ...
- poj1703 并查集
输入是2个不在一起的人,可以用一个数组来保存和他矛盾的人.这样find的时候就find(hash[]);就可以: #include<stdio.h> #include<string. ...
- sql-distinct
DISTINCT 找出表格内的不同资料的值 语法 SELECT DISTINCT "栏位名" FROM "表格名"; 例如:要在以下的表格,Store_Info ...
- mysql-函数FOUND_ROWS()
FOUND_ROWS() SELECT语句中经常可能用LIMIT限制返回行数.有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句.那么,在SELECT查询中包含SQL_CAL ...
- firefox(ff)下无法显示bootstrap图标问题的解决方案(转)
原文链接: http://www.th7.cn/web/html-css/201502/82548.shtml 后在网上搜到了解决方案,在此分享以供各位遇到问题的同好参考:在ff的地址栏中输入“abo ...
- 从ICLassFactory 为 CLSID的COM组建创建实例失败:c001f011
在sqlserver创建计划任务的时候,保存时出现:“从ICLassFactory 为 CLSID的COM组建创建实例失败:c001f011”. 解决方法:在运行sqlserver时,使用“以管理员身 ...
- BZOJ2186 欧拉函数
欧拉函数:一般记作φ(n),表示1-n中与n互质的数的数量. 欧拉函数是积性函数,即φ(m*n)=φ(m)*φ(n) //这条定理基友面试时还遇到了= = 欧拉函数的值φ(n)=n*(1-p[1])* ...
- 洛谷P2024 食物链
挺神奇 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种 ...
- Matplotlib中文设置
1.中文设置方法,代码前加入语句 from pylab import mpl mpl.rcParams['font.sans-serif'] = ['SimHei'] 2.例子 # -*- codin ...
- 菲涅尔反射(Fresnel Reflection)
离线渲染中,通常可以用kd,ks,kt(分别代表物体的漫反射系数,镜面反射系数,透射系数)来简单地描述一个物体的基本材质,例如,我们将一个物体设置为:kd=0,ks=0.1,kt=0.9,即代表一束光 ...