首页 > 代码库 > c#基础知识

c#基础知识

1.string与StringBuilder

   string 是不可变的,是引用类型继承与Object(值类型继承于ValueType),每次拼接string其实是在托管堆上构造一个新的对象。这样在反复的拼接字符串的时候就会产生大量的垃圾字符串,由GC自动回收,这个时候GC会频繁的回收垃圾字符串,影响性能,所以通常推荐使用StringBuilder来做字符串拼接,

        那么string支持字符串拼接的意义何在呢?

         这里就得说到字符串池这个概念,当我们创建一个字符串的时候,会先去字符串池中找(哈希表),如果没有找到就会创建一个新的字符串并保存到字符串池中,当创建的字符串已经在字符串池中存在的时候,就会去引用。这样已经创建过的字符串就可以共享,节省空间。因为在程序中,我们会使用大量的字符串,假如我们每次出现的字符串都在内存空间中开辟一块空间来存储,就会在内存中产生大量相同的字符串,也会造成垃圾回收频繁的执行,影响性能。所以string的字符串拼接适合少量的拼接,对于大量的拼接,则推荐使用StringBuilder。

      下面说说string的字符串拼接与StringBuilder拼接的简单过程。

 string的字符串拼接过程:string a=‘A‘; a+=B;

1.开辟足够大的临时存储空间来保证足够存储字符串A和B。

2.将A复制到临时区的开始处。

3.将B复制到临时存储区的结尾处。

4.释放a的旧有内存。

5.给a分配新内存。

6.将临时存储空间的字符串复制到5中新开辟的内存,并将a的引用指向新内存。

  StringBuilder拼接的过程:StringBuilder是链式存储结构,构造函数初始化StringBuilder实例的大小,可存储的最大容量,当前字符串。当新添加的字符串大于当前StringBuilder剩余空间的时候,StringBuilder就会开辟出一块新的空间(大小=原大小*2),新字符串补充满剩余内存空间后,将剩下的字符串放入新开辟的内存空间。引用一下网上的一张图。

 

 2者之间的本质区别在于,string在字符串拼接的时候是创建一个新的对象来保存拼接后的字符串,而StringBuilder则是在原StringBuilder对象上开辟新的内存空间,是操作原对象而非string的创建新对象。

 

2.值类型一定在栈上吗?

  我们都知道值类型是存放在线程栈上面,但其实只有值类型作为临时变量的时候才存放在栈上,作为成员变量,存储在堆中。

1.引用类型的内部变量,即使是值类型,也会在引用类型被实例是一起存放在堆上,方法内部的值类型变量不会初始化,在执行方法的时候放在栈上面。

2.对于值类型的数组,因为数组是引用类型。所以数组内的值类型也在堆上。

3.闭包,lamda表达式。如下:           

     Action<int> act = a =>{  Console.WriteLine(a); };

C# 成的IL 会添加一个静态的辅助类,闭包内的局部变量 也会成为辅助类的成员变量,因此,这种值类型的局部变量也被分配到堆上。

闭包的陷阱:参考 菩提树下的杨过 :http://www.cnblogs.com/yjmyzz/archive/2009/03/13/1410924.html

using System;using System.Collections.Generic;namespace ConsoleTest{    class Program    {        static void Main(string[] args)        {            List<Action> ls = new List<Action>();            for (int i = 0; i < 10; i++)            {                                ls.Add(() => Console.WriteLine(i));                            }            foreach (Action action in ls)            {                action();            }            System.Console.Read();        }           }  }

结果:一连输出了10行完全相同的"10"(可能并没有按代码编写者的"意图",输出0到9)

看了链接里面其实是编译生成了一个类,类里面有一个变量i和打印i的方法,然后创建一个Action委托集合将方法赋值,最后遍历集合执行,在执行的时候i已经加到10了。所以要通过一个内部变量来避免这种陷阱。。

3.哈希表的实现方法?

 

 

 

             

 

  

    

c#基础知识