大哥来救命啊!!

xiaotupansy 2006-12-15 02:41:25
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication36
{
class Program
{
static void Main(string[] args)
{
string sb = "A";
StringBuilder sb1 = new StringBuilder("B");
operate(sb, sb1);
string c = sb.Insert(1, "C");
Console.WriteLine(sb + " " + sb1 + " " + c);
Console.ReadLine();
}
static void operate(string a, StringBuilder b)
{
a.Insert(1, "b");
b.Append("lalala");
}
}
}
为什么sb的值没变而sb1的值变了啊,它们不都是传递的引用么?
sb1的值又为什么会变啊?
哪位大哥给我讲讲清楚啊,我还不明白啊
我在java版里面也问了一个类似的问题
http://community.csdn.net/Expert/topic/5231/5231989.xml?temp=.6940729
有50分
...全文
200 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaotupansy 2006-12-15
  • 打赏
  • 举报
回复
上面的解释再加上java版大哥的解释就完全清楚了
1、变量类型
值 变 量:用于代表存储大小确定的值
引用变量:用于代表存储大小不定的值
2、变量存储
栈:分配的存储空间不可改变,在超过作用域后能够自动回收
堆:分配的存储空间可以改变,在超过作用域后需要垃圾回收
值 变 量:只在栈中申请一个与自己值域匹配的空间,用于存放自身的值
引用变量:先在栈中申请一个与 CPU 寻址能力匹配的空间,用于存放一个地址值
     再在堆中申请一个存放自身实例的空间,并把这个空间的首地址放入栈中预先申请的空间
变量名:都是程序代码中栈空间的首地址的代表,程序编译时,变量名会被替换为相对于栈首地址的偏移量
3、方法的参数传递
值 传 递:方法的形参申请自己的存储空间,运行时把方法调用时的实参值复制给形参的方式
引用传递:方法的形参不申请自己的存储空间,让方法的形参与实参共享同一存储地址的方式
4、Java的参数传递方式:值传递
对于值参数,把实参值复制给形参,所以值参传递时形参在方法中的改变不影响实参。
对于引用参数,也是把实参值复制给形参,只是这次复制的值是实参的栈空间中存放的值(栈中存了堆中的首地址值),也就是说:实参与形

参将共用同一个堆空间。为此:
方法中如果改变了堆空间中的内容,实参能同步改动;
方法中如果改变了形参本身的栈中值(存放了一个新的堆空间首地址值),由于是值传递,实参是不变的

本例中:
x.append(y);//把形参y的实例值加到形参x实例值中,改变的是形参x堆空间中的内容,a同步改动
y=x;//把形参x的栈中值复制给形参y,使x、y共用同一堆空间,改变的是形参y栈空间中的内容,b不变
liujia_0421 2006-12-15
  • 打赏
  • 举报
回复
呵呵..

TO:static void operate (StringBuilder x, StringBuilder y) {
x.append(y);
y = x;
}
这个赋值过程为什么没有起到作用呢?


其实道理也很简单:
x.append(y)是在x的地址空间上增加的y,而x的地址空间正是s1的地址空间,所以你可以看见s1的值变化了..

而y=x;时,相当于直接将y指向x的地址空间了,所以y是变化了,但为什么s2没有变化?原因是原来y指向的是s2的地址空间,而现在只是改变了y的指向,s2地址空间上的值并不会发生什么变化..
xiaotupansy 2006-12-15
  • 打赏
  • 举报
回复
谢谢大哥们,我明白了,感激不尽啊!!!!
cancerser 2006-12-15
  • 打赏
  • 举报
回复
先说明的是,string是引用类型
//
现在来回答楼长的疑问
原因就是和这两种类型的存储方式有关
先说string
他的运作方式很特殊比如str3=str1+str2; 先开辟一段缓存然后把str1 str2考进缓存连接上,然后在把str3指向这个缓存.看着很简单,其实不然
string的所有操作都遵循这一原则,也就是 (开空间,考字符,移指针)(记住了,这个很值钱)
a.Insert(1, "b");这个操作很明显就是 开空间,考字符,而没移指针 所以a还是a
c=a.Insert(1, "b"); c才是这结果
又好比 a=a.SubString();a才变成想要的值
StringBuilder
StringBuilder sb1 = new StringBuilder("B");
当执行new 的时候 内存会提前分配一段内存给它,和string不同,string是现用现分配
由于提前分配空间 针对这个空间的操作,指针就不会改变
b.Append("lalala");是在原有空间上继续写入,就不存在移指针的问题
//回答完毕
mobydick 2006-12-15
  • 打赏
  • 举报
回复
string 是引用类型,但是表现为值类型。
所以
a.Insert(1, "b");这段代码并没有改变a的值,只是改变的a在内存中的一个副本的值,改变后值由于没有被赋给一个变量,所以,改变后的值是不可能被访问到的。
如果这样写
a = a.Insert(1, "b");
就把改变后的值赋给了变量a。
xiaotupansy 2006-12-15
  • 打赏
  • 举报
回复
对了,还有一个问题,请大哥回答一下
static void operate (StringBuilder x, StringBuilder y) {
x.append(y);
y = x;
}
这个赋值过程为什么没有起到作用呢?
xiaotupansy 2006-12-15
  • 打赏
  • 举报
回复
liujia_0421(SnowLover)大哥回答我不少问题了,呵呵。
我都对你有印象了
shenzhimin 2006-12-15
  • 打赏
  • 举报
回复
liujia_0421(SnowLover) 呵呵,在这找到你了,请在看一下这个帖子

http://community.csdn.net/Expert/topic/5233/5233404.xml?temp=.5382044
cancerser 2006-12-15
  • 打赏
  • 举报
回复
听我慢慢道来
liujia_0421 2006-12-15
  • 打赏
  • 举报
回复
给你引用段文章吧:

当然了,string本质上肯定是引用类型,但是这个特殊的类却表现出值类型的特点:

判断相等性时,是按照内容来判断的,而不是地址

它肯定是一个引用类型没错,两个方面来看:

1. class string继承自object,而不是System.ValueType(Int32这样的则是继承于System.ValueType)
2. string本质上是个char[],而Array是引用类型,并且初始化时也是在托管堆分配内存的

微软设计这个类的时候估计是为了方便操作,所以重写了操作符和Equals方法,不然的话我们判断string相等得这样:

foreach(char c in s.ToCharArray()){...}

但是另外一个常用的对象微软却没有帮忙重写等值判断的方法:Array

这样int[] a = {1,2,3}和int b = {1,2,3},a == b?// false

还有一个容易搞错的地方是按引用传递还是按值传递的问题:

引用类型按引用传递,值类型按值传递,这些都不错。
一个引用类型,比如System.Array类,作为参数向一个方法传递时,传送的是指针,但是这两种代码是不是就意味着等效?

void Test(Array a)和void Test(ref Array a)

结果是并不完全等效。

如果在函数内部调用构造函数新建了对象并赋予参数,则函数外的变量不会受影响;
比如a = new ...

如果只是改动该参数(一个对象)的字段,则会有影响,此时加不加ref都是等效的。
比如a[i] = ...

而string类型的另外一个特殊性在于它是“不会变”的,每次操作string,都相当于新建了一个string对象,所以对于string来讲,void Test(String s)和void Test(ref String s)永远都是不一样的。在这里string再次表现出了值类型的特点,我们以为这是传值 - 实际上传送的还是地址,但是在操作的时候string被再次初始化,外部根本不能得到这个变化。

对于变量作用域的概念来讲,微软这么设计也是合理的:既然是函数内部建立的对象,外部就应该没有访问这个对象的能力,函数结束后,这些对象就会被GC收集,同样不会影响外面的程序。

liujia_0421 2006-12-15
  • 打赏
  • 举报
回复
TO:
string 是值类型
StringBuilder是引用类型




string肯定是引用类型,但这个引用类型又有一定的特殊性,在某种程度上又表现出值类型的特点为..


xiaotupansy 2006-12-15
  • 打赏
  • 举报
回复
oldmoon(电子商务人,电子商务路),
string是引用类型
你去google一下就知道了
jickie阿文 2006-12-15
  • 打赏
  • 举报
回复
StringBuilder 是动态对象,在Append的时候对新Append对象又重新分配地址空间。
并没有在原来的地址上修改内容
oldmoon 2006-12-15
  • 打赏
  • 举报
回复
string 是值类型
StringBuilder是引用类型

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧