由于String类型代表的是一个不可变的字符串,所以BCL提供了另一个名为System.Text.StringBuilder的类型,它允许我们有效的对字符串的字符执行动态操作,以创建一个String。

从逻辑上说,StringBuilder对象中包含一个字段,它引用由Char结构构成的一个数组。StringBuilder的成员允许我们操作这个字符,有效的缩减字符串的大小或者更改字符串中的字符。如果字符串变大,超过已经分配的字符的大小,StringBuilder就会自动的分配一个全新的、更大的数组,并开始使用新的数组,前一个数组会被垃圾回收器回收。用StringBuilder对象构建好字符串之后,为了将StringBuilder的字符“转换”成一个String,只需调用StringBuilder的ToString方法,在内部,该方法只是返回对StringBuilder内部维护的字符串的字段的一个引用,执行效率非常快,因为它不需要进行字符数组复制。

 

StringBuilder既是具体建造者(Builder)又是指导者(Director),最终生成一个复杂的String对象作为产品(Product)。在具体建造者只有一个的情况下,如果抽象建造者角色已经被省略掉,那么还可以省略掉指导者角色。让Builder角色自己扮演指导者与建造者双重角色。

 

    // Fields
    private const string CapacityField = "Capacity";
   
internal const int DefaultCapacity = 0x10;
   
internal IntPtr m_currentThread;
   
internal int m_MaxCapacity;
   
internal volatile string m_StringValue;
   
private const string MaxCapacityField = "m_MaxCapacity";
   
private const string StringValueField = "m_StringValue";
   
private const string ThreadIDField = "m_currentThread";

 

上面是StringBuilder的一些Fields,其中主要的字段是MaxCapacity和StringValue。 注意StringValue的定义有个Volatile。

 

C#中volatile 关键字指示一个字段可以由多个同时执行的线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。可变关键字仅可应用于类或结构字段。不能将局部变量声明为 volatile。

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。

没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。

以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

 

我们在使用StringBuilder的时候,先new一个实例,看看构造函数

public StringBuilder() : this(0x10)
{
}

public StringBuilder(int capacity) : this(string.Empty, capacity)
{
}

public StringBuilder(string value) : this(value, 0x10)
{
}

public StringBuilder(int capacity, int maxCapacity)
{
   
this.m_currentThread = Thread.InternalGetCurrentThread(); //获取线程ID
   
if (capacity > maxCapacity)
    {
       
throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity"));
    }
   
if (maxCapacity < 1)
    {
       
throw new ArgumentOutOfRangeException("maxCapacity", Environment.GetResourceString("ArgumentOutOfRange_SmallMaxCapacity"));
    }
   
if (capacity < 0)
    {
       
throw new ArgumentOutOfRangeException("capacity", string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_MustBePositive"), new object[] { "capacity" }));
    }
   
if (capacity == 0)
    {
        capacity
= Math.Min(0x10, maxCapacity);
    }
   
this.m_StringValue = string.GetStringForStringBuilder(string.Empty, capacity);
   
this.m_MaxCapacity = maxCapacity;
}

public StringBuilder(string value, int capacity) : this(value, 0, (value != null) ? value.Length : 0, capacity)
{
}

public StringBuilder(string value, int startIndex, int length, int capacity)
{
   
this.m_currentThread = Thread.InternalGetCurrentThread();
   
if (capacity < 0)
    {
       
throw new ArgumentOutOfRangeException("capacity", string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_MustBePositive"), new object[] { "capacity" }));
    }
   
if (length < 0)
    {
       
throw new ArgumentOutOfRangeException("length", string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum"), new object[] { "length" }));
    }
   
if (startIndex < 0)
    {
       
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
    }
   
if (value == null)
    {
        value
= string.Empty;
    }
   
if (startIndex > (value.Length - length))
    {
       
throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength"));
    }
   
this.m_MaxCapacity = 0x7fffffff;
   
if (capacity == 0)
    {
        capacity
= 0x10;
    }
   
while (capacity < length) //如果长度大于了容量,则扩容2倍
    {
        capacity
*= 2;
       
if (capacity < 0)
        {
            capacity
= length;
           
break;
        }
    }
   
this.m_StringValue = string.GetStringForStringBuilder(value, startIndex, length, capacity);
}

相关文章:

  • 2022-12-23
  • 2021-05-25
  • 2022-12-23
  • 2021-06-06
  • 2022-12-23
  • 2021-05-01
  • 2021-09-07
猜你喜欢
  • 2022-12-23
  • 2022-01-21
  • 2021-08-12
  • 2021-05-29
  • 2021-11-30
相关资源
相似解决方案