首页 新闻 会员 周边

关于C#string的类型

0
悬赏园豆:20 [已关闭问题]

class Class1
{
    static void StrChange(string str)
    {
      str = "hellow";
    }

    static void Main()
    {
      string str = "123";//申明一个字符串
      StrChange(str);//调用方法
      Console.WriteLine(str);//输出字符串
    }
}

输出的结果是 "123"
string 到底是值类型还是引用类型?
如果是值类型,结果倒还说的过去.但是我记得string 是引用类型啊...难道是我记错了??
如果是引用类型的话.输出的结果应该是: "hellow"
请问这是为什么啊?? 大家帮忙解释一下..谢谢

问题补充: class Program { //引用类型 class SomeRef { public int x; } //值类型 struct SomeVal { public int x; } private static void ChangeRef(SomeRef r) { r.x = 555; } private static void ChangeVal(SomeVal v) { v.x = 5556; } static void Main(string[] args) { SomeRef r1 = new SomeRef();//分配在托管堆上 SomeVal v1 = new SomeVal(); r1.x = 5;//解析指针 v1.x = 5; ChangeRef(r1); ChangeVal(v1); Console.WriteLine(r1.x); Console.WriteLine(v1.x); } }
小AI的主页 小AI | 菜鸟二级 | 园豆:354
提问于:2010-04-04 15:45
< >
分享
其他回答(7)
0

我的理解是这样的:

   StrChange是传值调用,传进去的是一个地址,相当于一个指针,这个指针是str的一个副本,在函数中,这个副本分配了一个内存空间,指向了“hellow”, 但是str的对应的内存空间并没有改变。如果在StrChange中改变str的值,可以这样声明:

static void StrChange(ref string str)
        {
            str = "hellow";
        } 

这样使用:

 StrChange(ref str);//调用方法

ref的意思是把str的值传入到函数中,又分配了一块内存空间。

不知解释清楚了没

小丁 | 园豆:301 (菜鸟二级) | 2010-04-04 16:13
你说的这个我是知道的,主要是书上说string是引用类型,但是你看看我在问题补充中SomeRef经过重新赋值后,打印出来的值已经变了,我就是搞不清楚string到底特殊在什么地方啊
支持(0) 反对(0) 小AI | 园豆:354 (菜鸟二级) | 2010-04-04 16:37
@贺爱平:还是一样的解释,String也是对象并不特殊,函数ChangeRef接受一个拷贝,拷贝改变了引用的值,所以原来的指针对应的引用也改变了值,String类型特殊在: 如果两个String的字符串相等,它们对应的是同一个引用,比如:String str1 = "Hello"; String str2 = "Hello";str1和str2对应的是同一个引用,并且不可改变。如果把str2 重新赋值:str2 = "Hello2";那么内存就会生成一个字符串为"Hello2"的对象,然后把str2指向这个生成的对象。所以string也是引用类型,只是它特殊在如何去指向这个引用。
支持(0) 反对(0) 小丁 | 园豆:301 (菜鸟二级) | 2010-04-05 09:25
0

string是内置引用类型,但参数的引用类型与这个不是同一概念,加个ref则结果不同。

请看
http://www.cnblogs.com/downmoon/archive/2007/12/29/1019301.html

邀月 | 园豆:25475 (高人七级) | 2010-04-04 16:48
谢谢关于ref和out这个的概念我是知道的,我看看 啊
支持(0) 反对(0) 小AI | 园豆:354 (菜鸟二级) | 2010-04-04 17:00
0

string 是特殊的引用类型,为特例

WizardWu | 园豆:1402 (小虾三级) | 2010-04-04 17:00
0

1.string 是引用类型,它是一个横定量,不可变的,还有个字符串驻留~~~

至于你的那个啊:

可以这样理解:

  string str = "123";//str指向 字符串对性"123" 的地址(注意"123"就是一个对象,赋值操作只是对其引用)

   StrChange(str);//传参,将str对象的指针拷贝作为参数传递

  static void StrChange(string str) 
    { 
      str = "hellow"; //在这里只是str的拷贝复制,因此对原来的str没有影响
    } 

////////////////////////////////

你可以试一下下面,就可以得到结果“hellow”,对引用类型ref传参

引用类型的传参其实也是传拷贝,只是传的是引用地址的拷贝,而非对象本身~~

  static void StrChange(ref string str) 
    { 
      str = "hellow"; 
    } 

//ps:其实string实际上可以说除去字符串驻留之外和平常的引用类型的行为时一模一样的。只是string 因为可以将如:"hellow" 当成一个对象,我们永远只能对其引用,string的本身就是它的值的啊!!!你怎么去修改它呢??再说string实在clr的元类型,其的值是恒定的~~~

2.补充问题里面:结果应该是 555 5

结构体就不说了,类中的值类型成员实例在内存中也是放在堆中,她的操作也是引用的行为:)

 

ps:这里是你必须知道的。net,你可以看一下,他说得很清楚~~呵呵

http://www.cnblogs.com/anytao/mytag.aspx?tag=《你必须知道的.NET》&page=1

LittlePeng | 园豆:3445 (老鸟四级) | 2010-04-04 17:00
你的结果是错误的,应该是 555 5
支持(0) 反对(0) 小丁 | 园豆:301 (菜鸟二级) | 2010-04-05 09:26
@小丁:哦,对我看错了~~呵呵
支持(0) 反对(0) LittlePeng | 园豆:3445 (老鸟四级) | 2010-04-05 14:23
0

在面向对象里面,理想的情况下“一切都是对象”, 但为了方便(比如不用new就可以使用),Java和C#都定义了int、bool、string...它们不是对象,它们叫做“简单类型”。 简单类型都是值传递的。string还有另外的特别之处,有兴趣可去我的博客看看, 刚写完, ^_^。

☆大森林☆ | 园豆:85 (初学一级) | 2010-04-04 21:55
0

建议你读一下,《你必须知道的.net》中的8.3节-- 如此特殊:大话string

ForFreeDom | 园豆:589 (小虾三级) | 2010-04-05 11:52
0

String是引用类型,这是不用质疑的,但是String引用的对象非常特殊。

C#为了减少字符串的内存占用,采取了这样的策略,相同的字符串使用相同的内存空间,比如string a = "123"和string b = "123",虽然是两个string,但它们指向同一个内存地址。

请注意string由此带来的特殊性,假如此刻给a重新赋值:a = "456",原先那个内存地址中存放的依旧是"123"这是无法修改的,所以只能修改a的内存指向。

现在我们来看方法传值,普通的Object o传递进方法Me(Object o),真正的过程是,先新建一个新的变量o1(假设是这个名字),然后把o的引用地址复制给o1,现在o和o1引用相同的对象。现在在方法中修改o1.Name = "新名字",修改的是被o和o1共同引用的对象,因此o.Name自然也会变成新名字。

再看String,string s = "旧名字",传递进Me(string s),真正的过程是,先新建一个新的变量s1,然后把s的引用地址复制给s1,现在s和s1引用相同的字符串内存地址。方法中修改s1="新名字",由于原先的内存中的"旧名字"无法修改成"新名字",所以就需要新建一个内存空间存"新名字",然后将新的地址给s1,所以这时s和s1已经引用的不是同一个地址了!所以s和s1才会不相同。

请注意,这个机制很特殊,它既不是普通的对象那样,也和按值传递不同,按值传递是将整个值传了一个拷贝进去,因此无论怎么修改也两不干扰。

写的尽可能通俗易懂了,尽可能白话了,应该理解了吧?

Coki | 园豆:245 (菜鸟二级) | 2010-04-07 17:29
补充: 没搞懂你问题补充是为了说明什么…… SomeRef会被初始化在堆上,SomeVal会被初始化在栈上,ChangeRef时,形参r会获得和r1相同的地址引用,ChangeVal时,形参v会获得v1的一个完整的拷贝,然后再被放在栈的一个新区域去。 所以,r1被传进ChangeRef之后,r的改变即为r1的改变,而v1被传递进ChangeVal之后,其实传递的是一个完整的包含值的拷贝,此时v与v1已经没有任何关系。 所以之后r1被修改了,而v1没有改变。 正好印证了我的以上说法。
支持(0) 反对(0) Coki | 园豆:245 (菜鸟二级) | 2010-04-11 19:04
应该说是和string是有差别的。
支持(0) 反对(0) Coki | 园豆:245 (菜鸟二级) | 2010-04-12 08:45
0

你直接写成  Console.WriteLine(StrChange(str));   尝试下。

/aiq浪子飞龙 | 园豆:1189 (小虾三级) | 2010-04-09 22:15
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册