你真的了解.NET中的String吗?

你真的了解.NET中的String?

Terrylee20051225

概述

String在任何语言中,都有它的特殊性,在.NET中也是如此。它属于基本数据类型,也是基本数据类型中唯一的引用类型。字符串可以声明为常量,但是它却放在了堆中。希望通过本文能够使大家对.NET中的String有一个深入的了解。

不可改变对象

.NETString是不可改变对象,一旦创建了一个String对象并为它赋值,它就不可能再改变,也就是你不可能改变一个字符串的值。这句话初听起来似乎有些不可思议,大家也许马上会想到字符串的连接操作,我们不也可以改变字符串吗?看下面这段代码:

 1using System;
 2
 3namespace Demo1
 4{
 5    /**<summary>
 6    /// String连接测试
 7    /// </summary>
 8    public class Test
 9    {
10        public static void Main(string[] args)
11        {
12            string a = "1234";
13            Console.WriteLine(a);
14
15            a += "5678";
16            Console.WriteLine(a);
17            Console.ReadLine();
18        }
19    }
20}
21

运行的结果:

1234

12345678

看起来我们似乎已经把MyStr的值从“1234”改为了“12345678”。事实是这样的吗?实际上并没有改变。在第5行代码中创建了一个String对象它的值是“1234”,MyStr指向了它在内存中的地址;第七行代码中创建了一个新的String对象它的值是“12345678”,MyStr指向了新的内存地址。这时在堆中其实存在着两个字符串对象,尽管我们只引用了它们中的一个,但是字符串“1234”仍然在内存中驻留。

引用类型

前面说过String是引用类型,这就是如果我们创建很多个相同值的字符串对象,它在内存中的指向地址应该是一样的。也就是说,当我们创建了字符串对象a,它的值是“1234”,当我们再创建一个值为“1234”的字符串对象b时它不会再去分配一块内存空间,而是直接指向了a在内存中的地址。这样可以确保内存的有效利用。看下面的代码:

 1using System;
 2
 3namespace Demo2
 4{
 5    /**<summary>
 6    /// String引用类型测试
 7    /// </summary>
 8    public class Test
 9    {
10        public static void Main(string[] args)
11        {
12            string a = "1234";
13
14            Console.WriteLine(a);
15
16            Test.Change(a);
17
18            Console.WriteLine(a);
19            Console.ReadLine();
20        }
21
22        public static void Change(string s)
23        {
24            s = "5678";
25        }
26    }
27}


运行结果:

1234

1234


做一个小改动,注意Change(ref string s)

 1using System;
 2
 3namespace Demo2
 4{
 5    /** <summary>
 6    /// String引用类型测试
 7    /// </summary>
 8    public class Test
 9    {
10        public static void Main(string[] args)
11        {
12            string a = "1234";
13
14            Console.WriteLine(a);
15
16            Test.Change(ref a);
17
18            Console.WriteLine(a);
19            Console.ReadLine();
20        }
21
22        public static void Change(ref string s)
23        {
24            s = "5678";
25        }
26    }
27}
28


运行结果:

1234

5678

字符串的比较

.NET中,对字符串的比较操作并不仅仅是简单的比较二者的值,= =操作首先比较两个字符串的引用,如果引用相同,就直接返回True;如果不同再去比较它们的值。所以如果两个值相同的字符串的比较相对于引用相同的字符串的比较要慢,中间多了一步判断引用是否相同。看下面这段代码:

 1using System;
 2
 3namespace Demo3
 4{
 5    /** <summary>
 6    /// String类型的比较
 7    /// </summary>
 8    public class Test
 9    {
10        public static void Main(string[] args)
11        {
12            string a = "1234";
13            string b = "1234";
14            string c = "123";
15            c += "4";
16
17            int times = 1000000000;
18            int start,end;
19            
20            /**测试引用相同所用的实际时间
21            start = Environment.TickCount;
22            for(int i=0;i<times;i++)
23            {
24                if(a==b)
25                {}
26            }
27            end = Environment.TickCount;
28            Console.WriteLine((end-start));
29            
30            /**测试引用不同而值相同所用的实际时间
31            start = Environment.TickCount;
32            for(int i=0;i<times;i++)
33            {
34                if(a==c)
35                {}
36            }
37            end = Environment.TickCount;
38            Console.WriteLine((end-start));
39
40            Console.ReadLine();
41        }
42    }
43}
44

执行的结果(运行的结果可能有些不同):

1671

4172

由此我们看出值相同时的比较用= =比引用相同时的比较慢了好多。这里仅仅是一个测试,因为做这样的比较并没有任何实际的意义。
有一点需要明确的是,.NET==Equals()内部机制完全是一样的,==是它的一个重载。

1public static bool operator ==(string a, string b)
2{
3      return string.Equals(a, b);
4}
5

 1public static bool Equals(string a, string b)
 2{
 3      if (a == b)
 4      {
 5            return true;
 6      }
 7      if ((a != null) && (b != null))
 8      {
 9            return a.Equals(b);
10      }
11      return false;
12}
13

字符串驻留

看一下这段代码:

 1using System;
 2
 3namespace Demo4
 4{
 5    /**<summary>
 6    /// String的驻留
 7    /// </summary>
 8    public class Test
 9    {
10        public static void Main(string[] args)
11        {
12            string a = "1234";
13            string s = "123";
14            s += "4";
15
16            string b = s;
17            string c = String.Intern(s);
18
19            Console.WriteLine((object)a == (object)b);
20            Console.WriteLine((object)a == (object)c);
21            Console.ReadLine();
22        }
23    }
24}
25

执行的结果:

False

True

在这段代码中,比较这两个对象发现它的引用并不是一样的。如果要想是它们的引用相同,可以用Intern()函数来进行字符串的驻留(如果有这样的值存在)。

StringBuilder对象

通过上面的分析可以看出,String类型在做字符串的连接操作时,效率是相当低的,并且由于每做一个连接操作,都会在内存中创建一个新的对象,占用了大量的内存空间。这样就引出StringBuilder对象,StringBuilder对象在做字符串连接操作时是在原来的字符串上进行修改,改善了性能。这一点我们平时使用中也许都知道,连接操作频繁的时候,使用StringBuilder对象。但是这两者之间的差别到底有多大呢?来做一个测试:

 1using System;
 2using System.Text;
 3
 4namespace Demo5
 5{
 6    /**<summary>
 7    /// StringStringBulider比较
 8    /// </summary>
 9    public class Test
10    {
11        public static void Main(string[] args)
12        {
13            string a = "";
14            StringBuilder s = new StringBuilder();
15
16            int times = 10000;
17            int start,end;
18            
19            /**测试String所用的时间
20            start = Environment.TickCount;
21            for(int i=0;i<times;i++)
22            {
23                a += i.ToString();
24            }
25            end = Environment.TickCount;
26            Console.WriteLine((end-start));
27            
28            /**测试StringBuilder所用的时间
29            start = Environment.TickCount;
30            for(int i=0;i<times;i++)
31            {
32                s.Append(i.ToString());
33            }
34            end = Environment.TickCount;
35            Console.WriteLine((end-start));
36
37            Console.ReadLine();
38        }
39    }
40}
41


运行结果:

884

0

通过上面的分析,可以看出用String来做字符串的连接时效率非常低,但并不是所任何情况下都要用StringBuilder,当我们连接很少的字符串时可以用String,但当做大量的或频繁的字符串连接操作时,就一定要用StringBuilder

作者:TerryLee
出处:http://terrylee.cnblogs.com/

转载于:https://www.cnblogs.com/SunWentao/archive/2008/04/21/1164193.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

没有动任何配置文件,今天就出现了修改的JSP内容在页面不体现。依然是老的页面内容...

2019独角兽企业重金招聘Python工程师标准>>> 现象&#xff1a; 没有动任何配置文件&#xff0c;今天就出现了修改的JSP内容在页面不体现。依然是老的页面内容 问题分析: 既然可以用过&#xff0c;所以系统应该是检测文件更新的&#xff0c;之所以不重新编译JSP&…

DIV中class和id的区别

1.class是设置标签的类&#xff0c;id是设置标签的标识;2. 使用方法不同&#xff1a; class属性用于指定元素属于何种样式的类,如样式表可以加入.content1 { color: red; background: #ff80c0 } 使用方法&#xff1a;class"content1" id属性用于定义一个元素的独…

新浪微博api(.net)时间格式问题

Tue May 03 09:30:23 0800 2011 以前研究sinaapi的时候被这个时间格式纠结了好久&#xff0c;还自己写了一个函数去处理这种格式。最近在网上看到一个代码&#xff0c;很方便就解决了这个问题&#xff08;我就说.net怎么会没有这方法呢&#xff09;。 System.Globalization.Cul…

php代码上线,实现版本切换

以下为现有php业务&#xff0c;代码上线方式。实现&#xff1a;4套环境版本切换。[roothz-web-01 htdocs]# cat release.sh #!/usr/bin/env bashwork_dir/mnt/var/www/htdocs release_dir/var/www/htdocs# app environment app_env$1 # build release file path build_file_pat…

PWA

转载于:https://www.cnblogs.com/QianDingwei/p/11359160.html

Windows XP SP3?转自作者: 孤单的鸽子,  出处:天极yesky, 责任编辑: 袁绍龙

经过测试和检查之后&#xff0c;我们认为&#xff0c;SP3并未为Windows XP系统引入任何新的功能&#xff0c;它仅仅是一款安全升级和BUG修正补丁程序集……原文&#xff1a;http://winsystem.ctocio.com.cn/windowsxp/321/7492821.shtml目前&#xff0c;互联网上围绕Windows XP…

asp.net与JAVASCRIPT函数的相互调用

1.如何在JavaScript访问C#函数? 方法一&#xff1a; &#xff08;1&#xff09;、首先建立一个按钮&#xff0c;在后台将调用或处理的内容写入button_click中; &#xff08;2&#xff09;、在前台写一个js函数&#xff0c;内容为document.getElementById("btn1").…

汇编推荐书籍

1.《深入理解计算机系统》&#xff0c;必看&#xff01; 2.《see mips run linux》 &#xff0c; 千万不要认真看&#xff0c;看这本书的目录和小标题&#xff0c;了解mips需要学习些什么&#xff0c;而不是通过这本书来学基础知识&#xff0c;不懂的概念上网查就可以了&#x…

创建表头固定,表体可滚动的GridView(转)

本方法只需要设置一个GridView的宽度&#xff0c;其它宽度不需要设置。测试环境&#xff1a;IE6&#xff0c;Firefox通过。 C# <% Page Language"C#" AutoEventWireup"true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/…

3G与4G到底有何区别?

对每一个手机用户来说&#xff0c;3G和4G都是手机术语词典中最神秘的词汇&#xff0c;然而在任何卖手机和平板电脑的地方你都能发现它们的身影。当你想买一部手机的时候&#xff0c;通常不清楚该选择哪一种&#xff0c;但有一点要明确——不要随便追求高的数字。这篇文章将帮助…

海尔5D净水洗热水器引领中国制造未来

在过去的一段时间里&#xff0c;智能家居与物联网相继成为热潮&#xff0c;云计算与大数据开始被应用于不同领域的情况下&#xff0c;越来越多的智能家居产品也开始走入普通消费者生活之中……在这些独特的产业创新风起云涌的情况下&#xff0c;越来越多的行业开始推动着中国制…

Lambda表达式——注重过程的编程思想

一、使用匿名内部类的匿名对象创建线程和Lambda表达式写法 Lambda表达式写法不用去定义一个Runable接口的实现类&#xff1b; 二、方法入参是一个接口或者接口的实现类 三、对某个类的一些对象实例进行排序 其中&#xff0c;数组创建时候使用的是静态初始化&#xff0c;里面存放…

[转] STL中map用法详解

一&#xff0e;Map概述 Map是STL的一个关联容器&#xff0c;它提供一对一&#xff08;其中第一个可以称为关键字&#xff0c;每个关键字只能在map中出现一次&#xff0c;第二个可能称为该关键字的值&#xff09;的数据处理能力&#xff0c;由于这个特性&#xff0c;它…

HDU 1874 畅通工程续

畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9566 Accepted Submission(s): 3200 Problem Description某省自从实行了很多年的畅通工程计划后&#xff0c;终于修建了很多路。不过路多了也不好&am…

uboot中变量env(收集)

Env在u-boot中通常有两种存在方式&#xff0c;在永久性存储介质中&#xff08;flash、NVRAM等&#xff09;&#xff0c;在SDRAM中。可配置不适用env的永久存储方式&#xff0c;但不常用。U-boot在启动时会将存储在永久性存储介质中的env重新定位到RAM中&#xff0c;这样可以快速…

转换流

一、编码和解码 二、编码带来的问题 三、转换流InputStreamReader和OutputStreamWriter编码和解码的原理 看懂的字符变成看不懂的字节编码 和 把看不懂的字节编码变成看懂的字符&#xff1b; 字节和字符转换的桥梁&#xff0c;不写默认utf-8&#xff08;国际规定&#xff09;&a…

此情何时休

此情何时休 ——代腾飞 2008年5月6日 于成都 昨天你说今生要和我相依相守携手到白头 奈何今天你就突然说我们的缘分到了尽头 没有任何理由你就说要分手 你可知我的心里真的好难受 拉着你的手真的不想让你走 只是千言万语不知如何开口 只能轻轻松开你的手放你走 望着你远去的背…

BZOJ 3170: [Tjoi 2013]松鼠聚会 切比雪夫距离

3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id3170Description 有N个小松鼠&#xff0c;它们的家用一个点x,y表示&#xff0c;两个点的距离定义为&#xff1a;点(x,y)和它周围的8个点即上下…

序列化流

一、对象的序列化和反系列化 二、对象的序列化流ObjectOutputStream 标记型接口&#xff1a; 使用序列化流ObjectOutputStream将对象写入到文件中进行序列化&#xff1a; 执行过后的文件&#xff1a; 二进制字节存储&#xff0c;无法直接查看&#xff1b; 三、对象的反序列化流…

Asp.Net中虚拟文件系统的使用

具体实现步骤如下&#xff1a;一、开发web用户控件这一步和以前的开发没有区别。1、首先新建一个web应用程序(需要VS2005 sp1支持)2、然后在里面开发几个web用户控件3、在ascx文件上右键-〉属性-〉生成操作选择嵌入的资源4、生成dll就可以了(dll的名字为&#xff1a;Test.Contr…