先看下面: 原贴引用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 构造函数 阻断说”的理论~~~
{
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 构造函数 阻断说”的理论~~~
解决方案 »
- 关于命名空间system.management引用的问题
- 使用强类型DataSet数据实体,如何建立各层间对数据实体的实现或访问接口,实现松藕合的最佳折衷方案
- 小弟初学C#,各位大哥能不能给点意见或初级资料
- 如何得到上一个页面的控件值?
- C#读取Word和PPT的问题
- 如何变更ListViewItem中的项???
- 请问各位高手:Crystal Report可不可以自定义纸张大小的?怎么定义?急!!
- 哪位大哥有可用分相送啊 ??我不够分提问啊,
- 请教微软专家 ---- 好像是一个bug
- 成立虚拟小团队,开发自己的东西!有兴趣进来看看
- 谁能告诉我这个怎么实现啊~~~小白问题
- windows服务调用webservice 的问题.
2. 值类型.
3. 传引用.
4. 传值. 另外你还可以google "C++ 传指针 传指针的指针".
引用类型可以传值调用,值类型也可以引用调用,楼主不要将类型与调用搞混了。C#中,string 的确“特殊”,因为 string 是 Class,Class 是引用类型。参考MSDN中的说明:string 类型表示零或更多 Unicode 字符组成的序列。string 是 .NET Framework 中 String 的别名。
尽管 string 是引用类型,但定义相等运算符(== 和 !=)是为了比较 string 对象(而不是引用)的值。这使得对字符串相等性的测试更为直观。再看看 C# 中 String 的定义:
public sealed class String : IComparable, ......即 string 是一个密闭类。再看看其它的基本类型,如: int
int 在 .NET 中的类型是 System.Int32 System.Int32 的定义呢:
public struct Int32 : IComparable, ......
这是一个结构,结构是值类型。
第二个例子是改变引用类型的引用,相当于将传入的string指向了另一个string,自然也就看起来像是改变了其内容。
string类是很普通的引用类型,概念上一点都不特殊!
string 是引用类型,相等运算符(== 和 !=)是比较 string 对象的值!
普通引用类型,相等运算符(== 和 !=)是比较是否是同一对象(即引用)。string 特殊,指的就是这个。
但问题出在接下来的赋值上
str = "hellow";
相当于java的 str=new String("hellow");
也就是说 StrChange 内的 str 指向了一个新的实例。而不是改变了str原来实例的内容。
String实例的内容是永远也不会改变的。
这就是为什么有了 String 类还要来个 StringBuilder 类的原因。
public class Program
{
static void StrChange(StringBuilder str)
{
str.Remove(0, str.Length);
str.Append("hellow");
} static void Main(string[] args)
{
StringBuilder str = new StringBuilder("123");//申明一个字符串
StrChange(str);//调用方法
Console.WriteLine(str);//输出字符串
//显示 hellow
}
}
using System.Text;class Class1
{
static void StrChange(StringBuilder str)
{
str = new StringBuilder("hellow");
} static void Main()
{
StringBuilder str = new StringBuilder("123");//申明一个字符串
StrChange(str);//调用方法
Console.WriteLine(str);//输出字符串
}
}
//输出123
而不是说: static void StrChange(StringBuilder str)
{
str.Remove(0, str.Length);
str.Append("hellow");
}
你的代码其实是修改参数的数据,而不是修改的参数本书。其实你说的也没错,对。
class RefExample
{
static void Method(ref int i)
{
i = 44;
}
static void Main()
{
int val = 0;
Method(ref val);
// val is now 44
}
} 上面是msdn里的,什么是对参数的修改?就是对参数本身赋值,比如这个例子里的i=xxx,楼主的str=xxx。这跟数据类型是值还是引用类型没有关系,有人老把这些混在一起。
没有ref时:
值类型参数,对参数赋值无效(指不能影响到方法外部)。
引用类型参数,对参数赋值无效,但是可以通过访问对象的成员来改变某些成员的值,这可以影响到方法外部。
有ref时:
值类型参数,对参数赋值有效。
引用类型参数,对参数赋值有效,但这时已经不是原来的对象了;也可以通过访问对象的成员来改变某些成员的值,这可以影响到方法外部;对象还是原来的对象。
终于回到家中了,看到:
热闹了两天,后来就没戏了。
我想可能多数人“以为”问题己经清楚,到此为止了吧。[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]要觉觉了,其余明天再说~~
string 类重载了比较操作运算符,
先比较是否同一个引用,如果不是同一个引用再比较值是否一致.
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();
}
}
//首先我承认你,己经能够理解问题了.不过:我看你在"原贴"中的解说更加的复杂
关键:除了有人扔下一两个概念后,没有一个人把问题解说的明明白白.
更何况:还有各种各样,扰乱视听的说法,和复杂的解释[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的功底不到家"的家伙,更是可笑.
这个问题的争论,也不是一次两次的了。但还是有很多人老是弄不明白,从回帖中也可以看出来,除了wuyi8808和vrhero,没有几个能说到点子上的。都是微软的什么值类型、引用类型、按值传递、按引用传递这几个名词闹的,哈哈。
只是lz指的是原贴的“楼主”,不是我。顺便有感而发:
越是基础的内容,越是不容易把握,我想原因有这么几点:
[1]很多人自以为(我括我),在没有经历过“问题”时,一般也就突略过去了。
[2]基础内容的特殊性,反映了不规范的场景,不是所有人都会在意的。
[3]基础的东西,有时候不太好通过假调的方法来验证,需要理论知识。
[4]微软的有意回避,最多建议不采用而己。
[5]有些案例或说明不规范,造成了误导。以上5种情况,对本案例来说,全部存在:
比如说第[4]条,微软只抛下一句:Violates rule DoNotPassTypesByReference.
所以很难找到有关于引用类型的按引用传递的说明。
再比如经典书《C#3.0》第五版中,只对值类型的值|ref|out,传递方式做了详细的说明,同样忽略了引用类型。
其实最严重的是第[5]种情况,
出自于一些很高级的作者,书藉,不再一一列举(呵呵,主要是没有底气)...在CSDN中,
浮燥的人比比皆是,
认真做研究的,少之又少,
倒不是水平问题,主要还是在于态度,
不喜欢验证,不喜欢用代码来说明问题,随意猜测的胡乱回答的更多,
自己不明白,随意攻击提问者的真不少.呵呵,我是C#的初学者,刚刚入门,所以问题多一点.
csdn得好好学习一下cnblogs,虽然有点差异...