一个类型引发的争议!(String类型真的很特殊嘛?彻底晕了!)

微创社(MCC) 2009-07-29 09:55:16
先看下面: 原贴引用

using System;

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

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


再看下面:

using System;

class String
{
private string myString;

public String(string myString)
{
this.myString = myString;
}

public override string ToString()
{
return myString.ToString();
}

}

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

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


坚持string类型“特殊”说的大有人在,
比如string具有Immutable的特性,
从第二个案例来看,好象跟一般的引用类型没啥两样的,彻底晕了。

先热一下身,一会再势出一个“NEW 构造函数 阻断说”的理论~~~
...全文
469 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
soaringbird 2009-08-05
  • 打赏
  • 举报
回复
很简单的一个事情,让你弄得那么复杂
微创社(MCC) 2009-08-05
  • 打赏
  • 举报
回复

using System;

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

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




上述命题可以转化为下列“等价”命题

using System;

internal class ClassB
{
private string str;
public ClassB(string str)
{
this.str = str;
}
public void PrintVal()
{
Console.WriteLine(str);
}
}

class Test
{
static void Main()
{
ClassB a = new ClassB("123");
ClassB b = a;
a = new ClassB("hellow");
b.PrintVal();

Console.ReadKey();
}
}
//输出123


需要进一步进行验证,可看以下案例

using System;
using System.Text;
class Class1
{
static void StrChange(StringBuilder str)
{
Console.WriteLine("内部调用0:{0}", str);//形参不变(指向的实体不变123),实参不变(指向的实体不变123)
str.Replace("123", "hellow");
Console.WriteLine("内部调用1:{0}", str);//形参不变(指向的实体改变hellow),实参不变(指向的实体改变hellow)
str = new StringBuilder("hellowNEW");
Console.WriteLine("内部调用2:{0}", str);//形参改变(指向的实体改变hellowNEW),实参不变(指向的实体不变hellow)
str.Replace("hellowNEW", "hellowNEW123");
Console.WriteLine("内部调用3:{0}", str);//形参不变(指向的实体改变hellowNEW123),实参不变(指向的实体不变hellow)
}
static void Main()
{
StringBuilder str = new StringBuilder("123");//申明一个字符串,实参
StrChange(str);//调用方法
Console.WriteLine("外部调用0:{0}", str);//输出字符串,实参不变(指向的实体最后一次改变为hellow)
Console.ReadKey();
}
}
zwyDell 2009-08-05
  • 打赏
  • 举报
回复
学习~
微创社(MCC) 2009-08-05
  • 打赏
  • 举报
回复
是啊,呵呵
只是lz指的是原贴的“楼主”,不是我。

顺便有感而发:
越是基础的内容,越是不容易把握,我想原因有这么几点:
[1]很多人自以为(我括我),在没有经历过“问题”时,一般也就突略过去了。
[2]基础内容的特殊性,反映了不规范的场景,不是所有人都会在意的。
[3]基础的东西,有时候不太好通过假调的方法来验证,需要理论知识。
[4]微软的有意回避,最多建议不采用而己。
[5]有些案例或说明不规范,造成了误导。

以上5种情况,对本案例来说,全部存在:
比如说第[4]条,微软只抛下一句:Violates rule DoNotPassTypesByReference.
所以很难找到有关于引用类型的按引用传递的说明。
再比如经典书《C#3.0》第五版中,只对值类型的值|ref|out,传递方式做了详细的说明,同样忽略了引用类型。
其实最严重的是第[5]种情况,
出自于一些很高级的作者,书藉,不再一一列举(呵呵,主要是没有底气)

...

在CSDN中,
浮燥的人比比皆是,
认真做研究的,少之又少,
倒不是水平问题,主要还是在于态度,
不喜欢验证,不喜欢用代码来说明问题,随意猜测的胡乱回答的更多,
自己不明白,随意攻击提问者的真不少.

呵呵,我是C#的初学者,刚刚入门,所以问题多一点.
csdn得好好学习一下cnblogs,虽然有点差异...
soaringbird 2009-08-05
  • 打赏
  • 举报
回复
呵呵,楼主,其实你这种精神还是很值得学习的,我也知道你已经弄明白了。
这个问题的争论,也不是一次两次的了。但还是有很多人老是弄不明白,从回帖中也可以看出来,除了wuyi8808和vrhero,没有几个能说到点子上的。都是微软的什么值类型、引用类型、按值传递、按引用传递这几个名词闹的,哈哈。
微创社(MCC) 2009-08-05
  • 打赏
  • 举报
回复
楼上的不厚道啊.
//首先我承认你,己经能够理解问题了.

不过:我看你在"原贴"中的解说更加的复杂
关键:除了有人扔下一两个概念后,没有一个人把问题解说的明明白白.
更何况:还有各种各样,扰乱视听的说法,和复杂的解释

[1]string是值类型(这严重错误的人,并不多)
[2]string是特殊的引用类型(这个倒是不错,只是跟问题的本质无关)
[3]string是特殊的引用类型,它的实例是只读的
[4]string好像具有不变性
[5]函数内str所指内存,未改变函数外str(废话)
[6]string是引用类型,是不可变的,所以...
[7]string类型确实是比较特殊的引用类型
[8]重载了Equals,= 等(想当然)
[9]这个应该跟 C++ 指针参数类似。在 C# 里,除非声明为 ref (那是另一个问题)
[10]string是经过特殊处理了
[11]string是特殊的引用类型,它的实例是只读的(那又怎么样)3
[12]他的值是只读的 (听上去有道理,然后呢)
[13]楼主还是先去把变量的作用范围那块书看看吧(好象比谁都懂)
[14]immutable特性 (这是我犯的错误)
[15]你的string并没有new
[16]IL代码登场了(拜托,IL不是汇编,其实还是代码,只不过换一种写法嘛)
[17]引用但对 '='较为特殊而已

....简单和复杂本就是相对的

还有很多抨击"lz的功底不到家"的家伙,更是可笑.
heguo 2009-08-03
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 zming 的回复:]
引用 21 楼 heguo 的回复:
楼上还有很多人说到"特殊"两字.
string类是很普通的引用类型,概念上一点都不特殊!




string 是引用类型,相等运算符(== 和 !=)是比较 string 对象的值!
普通引用类型,相等运算符(== 和 !=)是比较是否是同一对象(即引用)。

string 特殊,指的就是这个。

[/Quote]

string 类重载了比较操作运算符,
先比较是否同一个引用,如果不是同一个引用再比较值是否一致.
微创社(MCC) 2009-08-02
  • 打赏
  • 举报
回复
[1]有感
终于回到家中了,看到:
热闹了两天,后来就没戏了。
我想可能多数人“以为”问题己经清楚,到此为止了吧。

[2]说明
我得承认,做了一回标题党“彻底晕了!”,其实我一点也不晕。
自打看到“原贴”后,发现自己对一些原本认为很“基础”的东西,原来并不真正的了解。
嗯,同样说来,其实一知半解的还是大有人在,所以很想把“心得”交流一下。
特别是想,论坛里有很多说法存在“严重错误”有必要澄清一下,以正视听。

[3]评论
1、6、13、16、17楼:酱油型或是还没有理解问题或是没有任何价值的评论
3、11、20楼:扔一些概念,但没有说明问题
4、19、22楼:画蛇添足,解说部分与问题毫不相干
7、14、18楼:误导的受害者,string特殊的结果
8楼:没说错,但也算酱油,没有新鲜的内容
10、23楼:我会给你新的例子,说明这个并不是问题的关键
11楼:第一个出来解决问题的人,首先提出用StringBuilder来替换,正好可以解决一下10楼的疑惑
15楼:很奇怪的矛盾,前半段是错误的,后半段还有点道理,不知道是否真的理解了
20楼:强化观点,没有进一步的说明
21楼:基本说对了,如果能进一步讲清楚函数体内关于NEW赋值的部分就完整了。
其余了不再一一罗列了,呵呵

[4]看代码是最好的办法,加上几组概念
形参、值参
值类型、引用类型
传值、传引用
栈、堆
隐式转换
装箱

using System;
using System.Text;
class Class1
{
static void StrChange(StringBuilder str)
{
Console.WriteLine("内部调用0:{0}", str);//形参不变(指向的实体不变123),实参不变(指向的实体不变123)
str.Replace("123", "hellow");
Console.WriteLine("内部调用1:{0}", str);//形参不变(指向的实体改变hellow),实参不变(指向的实体改变hellow)
str = new StringBuilder("hellowNEW");
Console.WriteLine("内部调用2:{0}", str);//形参改变(指向的实体改变hellowNEW),实参不变(指向的实体不变hellow)
str.Replace("hellowNEW", "hellowNEW123");
Console.WriteLine("内部调用3:{0}", str);//形参不变(指向的实体改变hellowNEW123),实参不变(指向的实体不变hellow)
}
static void Main()
{
StringBuilder str = new StringBuilder("123");//申明一个字符串,实参
StrChange(str);//调用方法
Console.WriteLine("外部调用0:{0}", str);//输出字符串,实参不变(指向的实体最后一次改变为hellow)
Console.ReadKey();
}
}


[5]要觉觉了,其余明天再说~~
jasonluo198x 2009-07-30
  • 打赏
  • 举报
回复
不明真相
cailee 2009-07-30
  • 打赏
  • 举报
回复
Mark 关注
vrhero 2009-07-30
  • 打赏
  • 举报
回复
另外...争议一词是指对没有准确结论的问题产生争论...而该帖的问题结论很清楚不存在争议,只不过是持错误观点的居多...
acqy 2009-07-30
  • 打赏
  • 举报
回复
楼主你第二个例子的输出结果写错了。

string是引用类型,本来第一个例子是可以改变引用类型内容的,但由于string是不可变的,因此在程序中会创建一个新的string,而并不会更改本身的内容。
第二个例子是改变引用类型的引用,相当于将传入的string指向了另一个string,自然也就看起来像是改变了其内容。
mythad 2009-07-30
  • 打赏
  • 举报
回复
string是引用类型,但具有值类型的特点!
vrhero 2009-07-30
  • 打赏
  • 举报
回复
1.string是特殊的引用类型,这是毫无疑问的...

2.那个引用帖子里产生的理解错误和string毫无关系,这也是毫无疑问的...

在那个引用帖子里不少人都给出了正确的答案和解释...但是因为该帖楼主错误标题的误导和新人回帖不看帖的传统恶习,很多人仍然在string的特殊性、构造函数甚至override等不想干的概念上瞎扯...
rightyeah 2009-07-30
  • 打赏
  • 举报
回复
基础知识太差, 对牛弹琴.
shrinerain 2009-07-30
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wuyi8808 的回复:]
原来那个帖子的问题不仅仅是对 string 类型,对一般的引用类型也是如此,并不是因为 string 的不可变性,而是因为没有使用 ref 关键字。即使把原贴中的 string 换成可变的 StringBuilder 结果也是一样的。
[/Quote]

对, 很简单的问题, 我让他去了解"传引用"和"传值"的概念.

他说"都很清楚", 既然如此, 我就不说了.

基础知识太差, 对牛弹琴.

wuyi8808 2009-07-30
  • 打赏
  • 举报
回复
原来那个帖子的问题不仅仅是对 string 类型,对一般的引用类型也是如此,并不是因为 string 的不可变性,而是因为没有使用 ref 关键字。即使把原贴中的 string 换成可变的 StringBuilder 结果也是一样的。
hecker728 2009-07-30
  • 打赏
  • 举报
回复
楼主我晓得你的意思??

你是说,第二个例子是你自己定义的String类型,,把它当做一般的普通引用类型来做比较。。

但是你存在一个误区,,你自己定义的String仍然使用了.net中的string 类型定义字段,以及处理。。

实质还是一样。结果自然也是那样。。

楼上的大虾已经把string类型怎么个特殊都列出来了,,记住就可以了。。
济南大飞哥 2009-07-30
  • 打赏
  • 举报
回复
CSDN上说的清楚,学的人家的东西,人家说什么就是什么喽!可以去看看!地址http://msdn.microsoft.com/zh-cn/library/system.string.aspx
acqy 2009-07-30
  • 打赏
  • 举报
回复
就是一个试图去修改“不变性”引用类型中的数据;另一个是修改“不变性”引用类型的引用本身。就这么简单。
换成c++的角度考虑,前者是修改指针所指向的内存区域中的数据(而这个数据是只读的,无法修改);后者是修改指针本身的值,即其所指向的内存区域的地址。
加载更多回复(21)

110,545

社区成员

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

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

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