C# string 特殊引用类型
C#有string关键字,在翻译成.NET类时,它就是System.String.有了它,像字符串连接和字符串复制这样的操作就简单了.
1. string 是引用类型还是值类型
引用类型操作
当使用重载操作符”=”给string对象赋值时,string的对象是引用类型,它保留在堆上,而不是堆栈上.因此,当把一个字符串赋给另一个字符串时,会得到对内存中同一个字符串的两个引用.例如,修改其中一个字符串,就会创建一个全新的string对象(注意,这个过程发生在”=”中),而另一个字符串没有改变.考虑下面的代码:
public class MyClass
{
public static void Main()
{
string str1 = "I am a number";
string str2 = str1;
Console.WriteLine("str1 = "+str1);
Console.WriteLine("str2 = "+str2);
str1 = "I am another number";
Console.WriteLine("after str1 changed... str1 = "+str1);
Console.WriteLine("after str1 changed... str2 = "+str2);
Console.ReadLine();
}
}
Output :
str1 = I am a number
str2 = I am a number
after str1 changed...str1 = I am another number
after str1 changed...str2 = I am a number
具有值类型特征的操作
string有两种情况下的操作是具有值类型特征的:
<!--[if !supportLists]-->1) <!--[endif]-->在函数中传递string(比如函数参数是string型)时,传递的是地址,但却不能修改成员变量,原因是它重新又创建了一个全新的对象,和它想修改的那个成员变量非同一地址,所以看上去像是值类型;
<!--[if !supportLists]-->2) <!--[endif]-->str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致).
总结:
string 到底是引用类型还是值类型 答:引用类型 . 只不过它在某此操作上会表现出值类型的特征.
string类型的另外一个特殊性在于它是“不会变”的,每次操作string,都相当于新建了一个string对象.
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
2. ”@”在string中的用法
都知道如果要使用转义字符的话,需要在字符前加上”\”,而C#提供了一种新的机制,使用”@”.在”@”后的字符串都看作是原意,不会解释为转义字符串.并且以”@”开头的字符串支持回车换行的显示方式(见下例).不过会增加到字符串长度,不推荐过多使用.
public class MyClass
{
public static void Main()
{
string str1 = @"HelloWorld!";
string str2 = @"line1: Hello
line2: World!";
Console.WriteLine("str1 length = "+str1.Length);
Console.WriteLine("str2 length = "+str2.Length);
Console.ReadLine();
}
}
Output :
str1 length = 11
str2 length = 34
3. String 和 string 的区别:
String是CLR(运行时库)的类型名字,而string是C#中的关键字.其实C#在编译时,会增加代码(下面列出的),将string转换成System.String.
using string = System.String;
using sbyte = System.SByte;
using byte = System.Byte;
using short = System.Int16;
using ushort = System.UInt16;
using int = System.Int32;
using uint = System.UInt32;
4. ”@”的其它用法
在 C# 规范中, ”@”可以作为标识符(类名、变量名、方法名等)的第一个字符,以允许C# 中保留关键字作为自己定义的标识符.
public class MyClass
{
public static void Main()
{
@class c = new @class();
c.@static();
Console.ReadLine();
}
public class @class
{
private int @bool;
public void @static()
{
Console.WriteLine("I've been staticed...and @bool is "+this.@bool);
}
public @class()
{
this.@bool = 999;
}
}
}
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
5. 等于null 和 等于””的区别
string = null; //不分配内存
string = “”; //分配字节为0的内存
-----------------------------------------------------------------------------------------------------------------------
有关C# String类型究竟是值类型还是引用类型,在很多C#学习者中都或多或少造成过困惑。好比下面这个例子:
- class Class1
- {
- static void StrChange(string str)
- {
- str = "hellow";
- }
- static void Main()
- {
- string str = "123";//申明一个字符串
- StrChange(str);//调用方法
- Console.WriteLine(str);//输出字符串
- }
- }
输出的结果是 "123" 。
那么,string 到底是值类型还是引用类型?有人会说,如果是值类型,结果倒还说的过去.但是string 的定义不是应该是引用类型么?如果是引用类型的话.输出的结果难度不应该是: "hellow"么?
解答这个问题的关键在于,C# string类型是特殊的引用类型,它的实例是只读的。这个地方要搞清楚语法和实现的区别 。在C#的语法中,
◆static void StrChange(string str) 是值传递
◆static void StrChange(ref string str) 是引用传递
但在实现上,static void StrChange(string str) 这种值传递,在函数体内对str进行修改之前,与函数外部的变量指向同一块内存,是“引用”传递,但在函数体内对str修改后,就会触发对该str重新分配一块内存。
所以说,String 是引用类型,不过是不可变的。对字符串做一些操作(比如大小写的转换、+=), 实际上是重新创建了一个字符串。这也是为什么在做大量字符串拼接的时候要使用StringBuilder 而不用+=。
有关C# String类型做为引用类型的特别之处,可以参看下例的示例及注释:
- private void button2_Click(object sender, EventArgs e)
- {
- string str="aaa";
- string str1 = str;
- str = "bbb";//注释掉此名就"yes",否则"no".这就说明str重新赋值的时候,
- //其实是重新创建了一个名为str的字符串(内存中指向的位置是不同的),先前
- //的那个str你就再也看不到了.
- string str2 = str;
- if (object.ReferenceEquals( str1,str2))
- {
- MessageBox.Show("yes");
- }
- else
- {
- MessageBox.Show("no");
- }
- }
最后回到一开始的那段代码。如果想下面这样编写:
- class Class1
- {
- static string StrChange(string str)
- {
- str = "hellow";
- return str;
- }
- static void Main()
- {
- string str = "123";//申明一个字符串
- str=StrChange(str);//调用方法
- Console.WriteLine(str);//输出字符串
- }
- }
这样输出的便是hellow了。