C# string 特殊引用类型

C#有string关键字,在翻译成.NET类时,它就是System.String.有了它,像字符串连接和字符串复制这样的操作就简单了.

1.  string 是引用类型还是值类型

引用类型操作

当使用重载操作符”=”给string对象赋值时,string的对象是引用类型,它保留在堆上,而不是堆栈上.因此,当把一个字符串赋给另一个字符串时,会得到对内存中同一个字符串的两个引用.例如,修改其中一个字符串,就会创建一个全新的string对象(注意,这个过程发生在”=”中),而另一个字符串没有改变.考虑下面的代码:

public class MyClass

{

      public static void Main()

      {

        string str1 = "I am a number";

        string str2 = str1;

        Console.WriteLine("str1 = "+str1);

        Console.WriteLine("str2 = "+str2);

       

        str1 = "I am another number"; 

        Console.WriteLine("after str1 changed... str1 = "+str1);

        Console.WriteLine("after str1 changed... str2 = "+str2);

           Console.ReadLine();

      }   

}

 

Output :

str1 = I am a number

str2 = I am a number

after str1 changed...str1 = I am another number

after str1 changed...str2 = I am a number

 

具有值类型特征的操作

string有两种情况下的操作是具有值类型特征的:

<!--[if !supportLists]-->1)        <!--[endif]-->在函数中传递string(比如函数参数是string型)时,传递的是地址,但却不能修改成员变量,原因是它重新又创建了一个全新的对象,和它想修改的那个成员变量非同一地址,所以看上去像是值类型;

<!--[if !supportLists]-->2)        <!--[endif]-->str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致).

总结:

string 到底是引用类型还是值类型   答:引用类型 .   只不过它在某此操作上会表现出值类型的特征.

string类型的另外一个特殊性在于它是“不会变”的,每次操作string,都相当于新建了一个string对象.
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

2.  ”@”在string中的用法

       都知道如果要使用转义字符的话,需要在字符前加上”\”,而C#提供了一种新的机制,使用”@”.在”@”后的字符串都看作是原意,不会解释为转义字符串.并且以”@”开头的字符串支持回车换行的显示方式(见下例).不过会增加到字符串长度,不推荐过多使用.

public class MyClass

{

      public static void Main()

      {

        string str1 = @"HelloWorld!";

        string str2 = @"line1: Hello

        line2: World!";

        Console.WriteLine("str1 length = "+str1.Length);

        Console.WriteLine("str2 length = "+str2.Length);

        Console.ReadLine();

      }   

}

Output :

str1 length = 11

str2 length = 34

 

 

3.  String 和 string 的区别:

       String是CLR(运行时库)的类型名字,而string是C#中的关键字.其实C#在编译时,会增加代码(下面列出的),将string转换成System.String.

using string = System.String;

using sbyte = System.SByte;

using byte = System.Byte;

using short = System.Int16;

using ushort = System.UInt16;

using int = System.Int32;

using uint = System.UInt32;

 

 

4.  ”@”的其它用法

       在 C#  规范中, ”@”可以作为标识符(类名、变量名、方法名等)的第一个字符,以允许C# 中保留关键字作为自己定义的标识符.

public class MyClass

{

      public static void Main()

      {

        @class c = new @class();

        c.@static();

        Console.ReadLine();

      }   

    public class @class

    {

        private int @bool;

        public void @static()

        {

            Console.WriteLine("I've been staticed...and @bool is "+this.@bool);

        }

        public @class()

        {

            this.@bool = 999;

        }

    }

}


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

5.  等于null 和 等于””的区别

       string = null; //不分配内存

       string = “”;     //分配字节为0的内存


-----------------------------------------------------------------------------------------------------------------------

  有关C# String类型究竟是值类型还是引用类型,在很多C#学习者中都或多或少造成过困惑。好比下面这个例子:

  1. class Class1   
  2. {   
  3.     static void StrChange(string str)   
  4.     {   
  5.       str = "hellow";   
  6.     }   
  7.  
  8.     static void Main()   
  9.     {   
  10.       string str = "123";//申明一个字符串   
  11.       StrChange(str);//调用方法   
  12.       Console.WriteLine(str);//输出字符串   
  13.     }   
  14. }   

    输出的结果是 "123" 。

    那么,string 到底是值类型还是引用类型?有人会说,如果是值类型,结果倒还说的过去.但是string 的定义不是应该是引用类型么?如果是引用类型的话.输出的结果难度不应该是: "hellow"么?

    解答这个问题的关键在于,C# string类型是特殊的引用类型,它的实例是只读的。这个地方要搞清楚语法和实现的区别 。在C#的语法中,

    ◆static void StrChange(string str) 是值传递

    ◆static void StrChange(ref string str) 是引用传递

    但在实现上,static void StrChange(string str) 这种值传递,在函数体内对str进行修改之前,与函数外部的变量指向同一块内存,是“引用”传递,但在函数体内对str修改后,就会触发对该str重新分配一块内存。

    所以说,String 是引用类型,不过是不可变的。对字符串做一些操作(比如大小写的转换、+=), 实际上是重新创建了一个字符串。这也是为什么在做大量字符串拼接的时候要使用StringBuilder 而不用+=。

    有关C# String类型做为引用类型的特别之处,可以参看下例的示例及注释:   

  1. private void button2_Click(object sender, EventArgs e)   
  2.       {   
  3.           string str="aaa";   
  4.  
  5.           string str1 = str;   
  6.           str = "bbb";//注释掉此名就"yes",否则"no".这就说明str重新赋值的时候,   
  7.           //其实是重新创建了一个名为str的字符串(内存中指向的位置是不同的),先前   
  8.           //的那个str你就再也看不到了.   
  9.           string str2 = str;   
  10.         
  11.             
  12.           
  13.           if (object.ReferenceEquals( str1,str2))   
  14.           {   
  15.               MessageBox.Show("yes");   
  16.           }   
  17.           else   
  18.           {   
  19.               MessageBox.Show("no");   
  20.           }   
  21.       }  

    最后回到一开始的那段代码。如果想下面这样编写:

  1. class Class1   
  2. {   
  3.       
  4.     static string StrChange(string str)   
  5.     {   
  6.       str = "hellow";   
  7.         return str;   
  8.     }   
  9.     static void Main()   
  10.     {   
  11.         string str = "123";//申明一个字符串   
  12.         str=StrChange(str);//调用方法   
  13.         Console.WriteLine(str);//输出字符串   
  14.     }   
  15.       
  16. }  

    这样输出的便是hellow了。

posted @ 2013-02-26 01:32  zagelover  阅读(348)  评论(0编辑  收藏  举报