.NET中的字符串(1):字符串 - 特殊的引用类型
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(); }
}

.NET中的字符串(1):字符串 - 特殊的引用类型的更多相关文章
- python中常用的一些字符串
capitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 center(width) 将字符串居中,并使用空格填充至长度 width 的新字符串 c ...
- [转载] linux查找目录下的所有文件中是否含有某个字符串
链接自 http://blog.sina.com.cn/s/blog_691a84f301015khx.html,并略加修订. 查找目录下的所有文件中是否含有某个字符串 find .|xargs gr ...
- js中获取URL中指定的查询字符串
js中获取URL中指定的搜索字符串,主要利用location对象实现,废话少说,上代码. function getSearchString(key) { // 获取URL中?之后的字符 var str ...
- PHP判断字符串中是否包含指定字符串,支持中文哦
RT,随手写的 /** * 判断字符串中是否包含指定字符串 * @var source 源字符串 * @var target 要判断的是否包含的字符串 * @return bool */ functi ...
- Mysql hql字符串字段中是否包含某个字符串,用 find_in_set
有这样一个需求,在Mysql数据库字符串字段(权限)中,有范围在 1 到 N 之间代表不同权限的值,分别被','分开,现在要取出具有某权限的所有成员列表. 创建表: 1 CREATE TABLE us ...
- 在stream流和byte[]中查找(搜索)指定字符串
在 stream流 和 byte[] 中查找(搜索)指定字符串 这里注重看的是两个 Search 的扩展方法,一个是 stream 类型的扩展,另一个是 byte[] 类型的扩展, 如果大家有更好的“ ...
- Java中XML格式的字符串4读取方式的简单比较
Java中XML格式的字符串4读取方式的简单比较 1.java自带的DOM解析. import java.io.StringReader; import javax.xml.parsers.Docum ...
- 在某个目录下的所有文件中查找包含某个字符串的Windows命令
findstr可以完成这个工作. 上面的命令表示,当前目录以及当前目录的所有子目录下的所有文件中查找"string"这个字符串. *.*表示所有类型的文件. /s 表示当前目录 ...
- linux查找目录下的所有文件中是否含有某个字符串
查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" find .|xargs grep -ri "IBM" -l ...
- 查找目录下的所有文件中是否含有某个字符串 linux
查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" 查找目录下的所有文件中是否含有某个字符串,并且只打印出文件名 find .|xar ...
随机推荐
- iterations 快捷键
原帖:https://blog.csdn.net/Soinice/article/details/83505198 为了防止删除备份的. iterations 快捷键 Live Templates 其 ...
- java+layui的Excel导入导出
html: <button class="layui-btn" onclick="exportData();">导出</button> ...
- wamp修改MySQL密码
wamp默认密码为空 用户名为root: 左击wamp绿色小图标,打开phpMyAdmin ->执行 ->账号 ->找到用户名为root的修改权限&&点击修改权限 - ...
- Python 多任务(线程) day2 (2)
同步 1.概念 :同步就是协同步调,按预定的先后次序运行 互斥锁 当多个线程几乎同时修改某一共享数据的时候,需要运行同步控制,最简单的同步机制是引入互斥锁.某个线程要更改共享数据时,先将其锁定,此时资 ...
- awk从放弃到入门(2):awk分隔符
一.awk分隔符 awk的默认分割符是空格,但是,这样描述并不精确,因为,awk的分隔符还分为两种,"输入分隔符" 和 "输出分隔符" . (1)输入分隔符:英 ...
- winform学习(7)Label控件、Button控件、TextBox控件
Label控件是System.Windows.Forms.Label 类提供的控件. 作用:主要用来提供其他控件的描述文字,例如:登录窗体上的用户名.密码(输入框前面的字) Button控件是Syst ...
- HTML前端入门归纳——布局
本人一直在从事.net的开发,界面都是采用的WPF,近期花了一个多月进行HTML前端的学习,在这里呢进行学习总结和归纳. 本系列将主要分为4个模块: 控件 样式 布局 JavaScript 根据多年W ...
- springmvc validator和springContext validator的区别
1.springContext validator 依赖于代理实现 MethodValidationInterceptor Set<ConstraintViolation<Object&g ...
- Bugku-CTF分析篇-中国菜刀(国产神器)
中国菜刀 国产神器
- (搬运)使用PHPstudy在Windows服务器下部署PHP系统
原帖地址:http://www.php.cn/php-weizijiaocheng-406175.html 这篇文章主要介绍了关于使用PHPstudy在Windows服务器下部署PHP系统,有着一定的 ...