C#string特殊的引⽤类型
.Net 框架程序设计(修订版)中有这样⼀段描述:String类型直接继承⾃Object,这使得它成为⼀个引⽤类型,也就是说线程上的堆栈上不会驻留有任何字符串。(译注:注意这⾥的“直接继承”。直接继承⾃Object的类型⼀定是引⽤类型,因为所有的值类型都继承⾃System.ValueType。值得指出的是System.ValueType却是⼀个引⽤类型)。
⼀:
string str1 = "string";
string str2 = "string";
Console.WriteLine(string.ReferenceEquals(str1, str2));
既然String类型是引⽤类型,那么代码⼀输出的应该是False,然⽽事实上代码⼀输出时的是True。
其实这是String类型的⾃动优化功能。str1,str2引⽤同⼀对象,节省内存,并不会为str2单独开辟内存空间。CLR使⽤了⼀种叫字符串驻留的技术,当CLR初始化时,会创建⼀个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引⽤。刚开始,散列表为空,JIT编译器编译⽅法时,会在散列表中查每
⼀个⽂本常量字符串,⾸先会查"abc"字符串,并且因为没有到,编译器会在托管堆中构造⼀个新的指向"abc"的String对象引⽤,然后将"abc"字符串和指向该对象的引⽤添加到散列表中。接着,在散列表中查第⼆个"abc",这⼀次由于到了该字符串,指向同⼀个String对象的引⽤会被保存在变量str2中,到此str1和str2指向了同⼀个引⽤,所以string.ReferenceEquals(str1, str2)就会返回true了。
另外,C#中是不允许⽤new操作符创建String对象的,编译器会报错。
⼆:
static void Main(string[] args) {
string str = "string";
Change(str);
Console.WriteLine(str);
}
static void Change(string str) {
str = "Changed";
}
⽅法传递的参数是原内容的拷贝,其过程如果⽤图可表⽰为:
语句str=”Changed”之前
语句str=”Changed”之后
这样可以看到原来String对象并未改变str=”Changed”只是创建⼀个新的String对象(其它引⽤类型是改
变内存地址1指向的值),因此这个⽅法的参数需要加上ref或者out修饰符。因此这⾥也可以得出字符串具有恒等性,也就是说⼀个字符串⼀旦被创建,我们就不能再将其变长、变短、或者改变其中的任何字符。
MSDN上这样解释:字符串对象是不可变的,即它们⼀旦创建就⽆法更改。对字符串进⾏操作的⽅法实际上返回的是新的字符串对象。
string在另⼀种情况下的操作是具有值类型特征的:str1 == str2 ,仅仅是⽐较了值,⽽⾮地址(是MS重写了==运算符所致).
三:
String 对象是不可改变的。每次使⽤ System.String 类中的⽅法之⼀时,都要在内存中创建⼀个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执⾏重复修改的情况下,与创建新的 String 对象相关的系统开销可能会⾮常昂贵。如果要修改字符串⽽不创建新的对象,则可以使⽤ System.Text.StringBuilder 类。例如,当在⼀个循环中将许多字符串连接在⼀起时,使⽤ StringBuilder 类可以提升性能。
下⾯看⼀个极简单的例⼦:
namespace TCP
{
public class Program
{
public class User
{
private string _name;
private string _age;
public User(string name, string age)
{
_name = name;
_age = age;
}
public string name
{
get { return _name; }
set { _name = value; }
}
public string age
{
get { return _age; }
set { _age = value; }
}
}
}
public static void editUser(User user, StringBuilder str,string code)
{
code = "VB.NET";
str = str.Remove(0, 1);
str.Append("E");
user.name = "LEE";
user.age = "10";
}
static void Main(string[] args)
{
string code = "C#";
User user = new User("Li","23");
StringBuilder str = new StringBuilder();
str.Append("A");
editUser(user, str,code);
Console.WriteLine(code);
Console.WriteLine(str);
Console.WriteLine(user.name);
Console.WriteLine(user.age);
字符串常量池存的是实例还是引用?
Console.ReadLine();
}
}
上⾯代码输如下:
从上⾯可以看到string类型的值并没有改变,StringBuilder与class的值都改变了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论