在任何语言中,String都无疑是非常特殊的一种数据类型。C#中也是如此。
string是System.String的alias。
alias用using声明,用法如下
using[alias=]class_or_namespace;
2
string是个独特的基本数据类型,它是基本数据类型中唯一的引用类型。作为基本数据类型,字符串可以声明为常量,但是却放在堆中。
字符串是唯一具有可变长度的基本数据类型
3
.NETFramework的String类型是不可变的。
不可改变的一个优点是它是线程安全的。
如果系统在编译时知道一个字符串中的字符是什么,就会内置这个字符串。被内置的字符串可以是一个常量,也可以不是。
把String定义为不可改变,它的表现像一个值类型,但实际上仍然是引用类型。
时刻记住的一点是:
任何对String的修改都会创建一个新String对象。
比如String.Replace(),String.ToLower()等待。
Const是初始化字符串最有效的方法,因为它涉及的IL指令最少。
4
String虽然是reference类型,但其分配却可以不使用new表达式,Stringobject的初始化可采用“适用于value型别”的语法。如:
stringstr="TestString";
此外:
C#Primer中文版(StanleyB.Lippman,侯捷/陈硕合译)中有这样一句:“如果声明的是Localarray,有一个简短表示法可以使我们不必再明确调用new表达式。”
虽然我对Localarray的确切定义不甚了解,但对于接下来的用法还是比较熟悉的。
string[]m_message=
{
"Hi,Pleaseenteryourname:",
"Oops,Invalidname,Pleasetryagain:",
//此处的","用不用都可
}
5
String虽然是reference类型,但是operators(==and!=)却定义为比较二者的值,而不是引用。
一个来自MSDN上的例子。
stringa="hello";
stringb="h";
b+="ello";//appendtob
Console.WriteLine(a==b);
//output:True--samevalue
Console.WriteLine((object)a==b);//False--differentobjects
6
String是reference类型没有错,但我试了以下代码后却让我感觉到String的特殊。
classClass1
{
staticvoidMain(string[]args)
{
Class1c=newClass1();
stringstr="123";
c.Change(str);
Console.WriteLine(str);
}
privatevoidChange(strings)
{
s="456";
}
}
结果却是:
123
做了小改动之后:
classClass1
{
staticvoidMain(string[]args)
{
Class1c=newClass1();
stringstr="123";
c.Change(refstr);
//加上ref关键字
Console.WriteLine(str);
Console.Read();
}
privatevoidChange(refstrings)
//加上ref关键字
{
s="456";
}
}
输出结果是:
456
7
对于值类型,如果对象的值相等,则相等运算符 (==) 返回 true,否则返回 false。对于string 以外的引用类型,如果两个对象引用同一个对象,则 == 返回 true。对于 string 类型,== 比较字符串的值。
==操作比较的是两个变量的值是否相等
equals()方法比较的是两个对象的内容是否一致.equals也就是比较引用类型是否是对同一个对象的引用。static void Main()
{
string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); //未开辟新内存空间,使用的还是a的内存空间,相当于a对象,它们两个在堆中使用的是一个内存空间.当建立b时,先在堆中查找有没有 所需要的内容,有的话,就直接指向,没有的话就新建一个
Console.WriteLine (a==b); //输出true,
Console.WriteLine (a.Equals(b)); //输出true,
object c = new object();
object d = new object(); //在堆中开辟新的内存空间,对象内容与c是不同的,与字符串对象不同,这样的对象建立的时间,不用在堆中查找有没有相同的内容,直接在堆内存中开辟一块新的内存空间.
Console.WriteLine(c == d); //输出false,因为cd它们两个在栈中的内容不一样
Console.WriteLine(c.Equals(d)); //输出false,因为虽然建立cd时所用的语法是一样的,但终究它们不是相同的对象,只有用object d=c;这样才是相同的对象
object e = new object();
object f = e; 新建立对象f,这时把已经有的对象赋给f,这样f就不会在堆内存中开辟新的内存空间,而是直接把,e的引用传给f,也就是把e在栈中的引用值,传到f在栈中的内存中.这样它们就同时指向了相同的椎内存.
Console.WriteLine(c == d);
Console.WriteLine(c.Equals(d));
}
说明equals比较的是堆中的内容,也就是两个对象的内容;
而==比较的是值,也就是栈中的内容.
总结,用string 建立新对象时,会在内存中查找有没有相同的内容,有的话,直接把新建立的对象指过去,没有的话,就在堆中开辟新的内存空间.这个string对象还是比较特殊的.
而用其它类新建立的对象,就没有在堆中查找的步骤,直接在堆内存中开辟一块新的内存空间.当然不包括下面这种形式:
object e = new object();
object f = e;
把新建立的对象以原有的对象赋值,这样就不会在堆内存中开辟新的空间.
以上内容是操作中得到的,正确与否,有待进一步考察.
(在java中好像以下是建立不相同的对象,也就是说在堆中的不共用内存,当然在栈内存中保留的引用也不相同,但彼此的堆内容是相同的,都是字符串"abc".
string a = new string("abc");
string b = new string("abc")