swollaws
漂泊中体会不到生活的味道,那是因为吃不到老妈烧的饭。

一、创建字符串

      1、string是一个不可变的数据类型,一旦对字符串对象进行了初始化,该字符串对象就不能改变了。修改字符串内容的方法和运算符实际上是创建一个新的字符串。

            例如:string text = "This is a introduction。";text += "This is a Text";从语法上看,后一行代码是把更多的文本添加到字符串中。实际上并非如此,而是创建一个新字符串实例,给它分配足够的内存,以保存合并起来的文本。最初的文本"This is a introduction。"复制到这个新字符串中,再加上额外的文本"This is a Text"。然后更新存储在变量text中的地址,使变量正确地指向新的字符串对象。旧的字符串对象被撤消了引用----不再有变量引用它,下一次垃圾收集器清理应用程序中所有未使用的对象时,就会删除它。所以需要对字符串变量进行多次操作时将使用下面介绍的内容。

      2、StringBuilder

            在使用String类构造一个字符串时,要给它分配足够的内存来保存字符串,但StringBuilder通常分配的内存会比需要的更多。开发人员可以选择显示指定,但如果没有显示指定,存储单元量在默认情况下就根据StringBuilder初始化时的字符串长度来确定。它有两个主要的属性:

                  2.1、Length 指定字符串的实际长度;

                  2.2、Capacity 是字符串占据存储单元的长度。

            对字符串的修改就在赋予StringBuilder实例的存储单元中进行,这就大大提高了添加子字符串和替换单个字符的效率。删除或插入子字符串仍然效率低下,因为这需要移动随后的字符串。只有执行扩展字符串容量的操作,才会给字符串分配需要的新内存,才可能移动包含的整个字符串。在添加额外的容量时,从经验来看,StringBuilder如果检测到容量超出,且该容量中没有显示设置新值,就会使自己的容量翻倍。

            例如:StringBuilder text = new  StringBuilder("This is a introduction。", 100);text.Append("This is a Text");

      一般,使用StringBuilder可以执行字符串的任何操作,String可以用于存储字符串或显示最终结果。

 二、格式化字符串

       格式字符串本身大都由要显示的文本组成,但只要有要格式化的变量,它在参数列表中的下标就必须放在括号中。在括号中还可以有与该项的格式相关的其他信息,例如可以包含:

      1、该项的字符串表示要占用的字符数,这个信息的前面应有一个逗号,负值表示该项应左对齐,正值表示该项应右对齐。如果该项占用的字符数比给定的多,其内容也会完整地显示出来。

      2、格式说明符也可以显示出来。它的前面应有一个冒号,表示应如何格式化该项。

      例如:double d = 45;int i = 10;Console.WriteLine("The double is {0,10:E}.", d);

      字符串的格式化

      就上面的double d = 45;int i = 10;Console.WriteLine("The double is {0,10:E}.", d);示例,实际上过程是

[HostProtection(SecurityAction.LinkDemand, UI = true)]

public static void WriteLine(string format, object arg0)

{

    Out.WriteLine(format, arg0);

}

跳转到下面的函数中

public virtual void WriteLine(string format, object arg0)

{

    this.WriteLine(string.Format(this.FormatProvider, format, new object[] { arg0 }));

}

其中上面这个方法中的WriteLine的定义为public virtual void WriteLine(string value){//代码省略,只是显示string.Format返回的字符串},而string.Format的定义为

public static string Format(IFormatProvider provider, string format, params object[] args)

{

    if ((format == null) || (args == null))

    {

        throw new ArgumentNullException((format == null) ? "format" : "args");

    }

    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));

    builder.AppendFormat(provider, format, args);

    return builder.ToString();

}

即最终跳转到StringBuilder的AppendFormat方法。【由于AppendFormat的内容比较多,这里不加显示,想了解具体方法体,可反编译System.dll查看】StringBuilder.AppendFormat()需要指出如何格式化对象,它首先检查对象,确认它是否执行System命名空间中的接口IFormattable。只要试着把这个对象转换为接口,看看转换是否成功即可。如果测试失败,AppendFormat()只会调用对象的ToString()方法,所有的对象都从System.Object继承了这个方法或重写了该方法。

      但是,所有预定义的基本数字类型都执行这个接口,对于这些类型,特别是这个示例中的double,就不会调用继承自System.Object的基本ToString()方法。为了理解这个过程,需要了解IFormattable接口。

      IFormattable只定义了一个方法,该方法也叫作ToString(),它带有两个参数,这与System.Object版本的ToString()不同,它不带参数。下面是IFormattable的定义:

[ComVisible(true)]

public interface IFormattable

{

    // Methods

    string ToString(string format, IFormatProvider formatProvider);

}

这个ToString()重载方法的第一个参数是一个字符串,它指定要求的格式。换言之,它是字符串的说明符部分,放在字符串的{}中。例如上面的示例double d = 45;int i = 10;Console.WriteLine("The double is {0,10:E}.", d);中,在double变量d上调用这个重载方式,传递给它的第一个参数是E,即格式说明符内冒号后面的文本。第二个参数暂时不介绍,但如果formatProvider为空,ToString()就要使用系统设置中指定的文化背景信息。下一个要格式化的对象是int,它不需要任何特殊的格式。由于没有格式要求,StringBuilder.AppendFormat()会给该格式字符串传递一个空引用,并适当地响应带有两个参数的ToString()重载方法。

      示例

  1. using System;
  2. using System.Text;
  3.  
  4. namespace Text
  5. {
  6.     class MainEntryPoint
  7.     {
  8.         static void Main()
  9.         {
  10.             Vector v1 = new Vector(1, 32, 5);
  11.             Vector v2 = new Vector(845.4, 54.3, -7.8);
  12.             Console.WriteLine("\nIn IJK format,\nv1 is {0,30:IJK}\nv2 is {1,30:IJK}", v1, v2);
  13.             Console.WriteLine("\nIn default format,\nv1 is {0,30}\nv2 is {1,30}", v1, v2);
  14.             Console.WriteLine("\nIn VE format\nv1 is {0,30:VE}\nv2 is {1,30:VE}", v1, v2);
  15.             Console.WriteLine("\nNorms are:\nv1 is {0,20:N}\nv2 is {1,20:N}", v1, v2);
  16.             Console.ReadLine();
  17.         }
  18.     }
  19.  
  20.     struct Vector : IFormattable
  21.     {
  22.         public double x, y, z;
  23.  
  24.         public Vector(double x, double y, double z)
  25.         {
  26.             this.x = x;
  27.             this.y = y;
  28.             this.z = z;
  29.         }
  30.  
  31.         public string ToString(string format, IFormatProvider formatProvider)
  32.         {
  33.             if (format == null) return ToString();
  34.             string formatUpper = format.ToUpper();
  35.             switch (formatUpper)
  36.             {
  37.                 case "N":
  38.                     return "|| " + Norm().ToString() + " ||";
  39.                 case "VE":
  40.                     return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
  41.                 case "IJK":
  42.                     StringBuilder sb = new StringBuilder(x.ToString(), 30);
  43.                     sb.Append(" i + ");
  44.                     sb.Append(y.ToString());
  45.                     sb.Append(" j + ");
  46.                     sb.Append(z.ToString());
  47.                     sb.Append(" k");
  48.                     return sb.ToString();
  49.                 default:
  50.                     return ToString();
  51.             }
  52.         }
  53.  
  54.         public Vector(Vector rhs)
  55.         {
  56.             x = rhs.x;
  57.             y = rhs.y;
  58.             z = rhs.z;
  59.         }
  60.  
  61.         public override string ToString()
  62.         {
  63.             return "( " + x + " , " + y + " , " + z + " )";
  64.         }
  65.  
  66.         public double this[uint i]
  67.         {
  68.             get
  69.             {
  70.                 switch (i)
  71.                 {
  72.                     case 0:
  73.                         return x;
  74.                     case 1:
  75.                         return y;
  76.                     case 2:
  77.                         return z;
  78.                     default:
  79.                         throw new IndexOutOfRangeException(
  80.                            "Attempt to retrieve Vector element" + i);
  81.                 }
  82.             }
  83.             set
  84.             {
  85.                 switch (i)
  86.                 {
  87.                     case 0:
  88.                         x = value;
  89.                         break;
  90.                     case 1:
  91.                         y = value;
  92.                         break;
  93.                     case 2:
  94.                         z = value;
  95.                         break;
  96.                     default:
  97.                         throw new IndexOutOfRangeException(
  98.                            "Attempt to set Vector element" + i);
  99.                 }
  100.             }
  101.         }
  102.  
  103.         private const double Epsilon = 0.0000001;
  104.  
  105.         public static bool operator ==(Vector lhs, Vector rhs)
  106.         {
  107.             if (Math.Abs(lhs.x - rhs.x) < Epsilon && Math.Abs(lhs.y - rhs.y) < Epsilon &&
  108.                 Math.Abs(lhs.z - rhs.z) < Epsilon)
  109.                 return true;
  110.  
  111.             return false;
  112.         }
  113.  
  114.         public static bool operator !=(Vector lhs, Vector rhs)
  115.         {
  116.             return !(lhs == rhs);
  117.         }
  118.  
  119.         public static Vector operator +(Vector lhs, Vector rhs)
  120.         {
  121.             Vector Result = new Vector(lhs);
  122.             Result.x += rhs.x;
  123.             Result.y += rhs.y;
  124.             Result.z += rhs.z;
  125.             return Result;
  126.         }
  127.  
  128.         public static Vector operator *(double lhs, Vector rhs)
  129.         {
  130.             return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
  131.         }
  132.  
  133.         public static Vector operator *(Vector lhs, double rhs)
  134.         {
  135.             return rhs * lhs;
  136.         }
  137.  
  138.         public static double operator *(Vector lhs, Vector rhs)
  139.         {
  140.             return lhs.x * rhs.x + lhs.y + rhs.y + lhs.z * rhs.z;
  141.         }
  142.  
  143.         public double Norm()
  144.         {
  145.             return x * x + y * y + z * z;
  146.         }
  147.     }
  148. }

 

posted on 2009-07-08 16:12  swollaw  阅读(264)  评论(0编辑  收藏  举报