• C#中特殊的string类型


                                                                                  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有两种情况下的操作是具有值类型特征的:

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

    2)        str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致).

    总结:

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

    string类型的另外一个特殊性在于它是“不会变”的,每次操作string,都相当于新建了一个string对象.

    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 的区别:

           StringCLR(运行时库)的类型名字,stringC#中的关键字.其实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;

            }

        }

    }



    5  等于null 等于””的区别

           string = null; //不分配内存

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

     

    Net 框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一个引用类型,也就是说线程上的堆栈上不会驻留有任何字符串。(译注:注意这里的“直接继承”。直接继承自Object的类型一定是引用类型,因为所有的值类型都继承自System.ValueType。值得指出的是System.ValueType却是一个引用类型)。

      一:

    string str1 = "string";
    string str2 = "string"
    Console.WriteLine(string.ReferenceEquals(str1, str2));

     

     既然String类型是引用类型,那么代码一输出的应该是False,然而事实上代码一输出时的是True。 
     

      其实这是String类型的自动优化功能。str1,str2引用同一对象,节省内存,并不会为str2单独开辟内存空间。CLR使用了一种叫字符串驻留的技术,当CLR初始化时,会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引用。刚开始,散列表为空,JIT编译器编译方法时,会在散列表中查找每一个文本常量字符串,首先会查找"abc"字符串,并且因为没有找到,编译器会在托管堆中构造一个新的指向"abc"的String对象引用,然后将"abc"字符串和指向该对象的引用添加到散列表中。接着,在散列表中查找第二个"abc",这一次由于找到了该字符串,指向同一个String对象的引用会被保存在变量str2中,到此str1和str2指向了同一个引用,所以string.ReferenceEquals(str1, str2)就会返回true了。


     

      另外,C#中是不允许用new操作符创建String对象的,编译器会报错。

      二:
     


    static void Main(string[] args) {
      string str = "string"
      Change(str); 
      Console.WriteLine(str); 
    static void Change(string str) { 
      str = "Changed"
    }

     

    方法传递的参数是原内容的拷贝,其过程如果用图可表示为:

     

      语句str=”Changed”之前

     

      语句str=”Changed”之后


      这样可以看到原来String对象并未改变str=”Changed”只是创建一个新的String对象(其它引用类型是改变内存地址1指向的值),因此这个方法的参数需要加上ref或者out修饰符。因此这里也可以得出字符串具有恒等性,也就是说一个字符串一旦被创建,我们就不能再将其变长、变短、或者改变其中的任何字符。

      MSDN上这样解释:字符串对象是不可变的,即它们一旦创建就无法更改。对字符串进行操作的方法实际上返回的是新的字符串对象。

      string在另一种情况下的操作是具有值类型特征的:str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致).

       三:

      String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类。例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。


     

      下面看一个极简单的例子:

    namespace TCP
    {
    public class Program
    {
        public class User
          {
              private string _name;
              private string _age;
              public User(string name, string age)
              {
                  _name = name;
                  _age = age;
              }

              public string name
              {
                  get { return _name; }
                  set { _name = value; }
              }
              public string age
              {
                  get { return _age; }
                  set { _age = value; }
              }
          }
       }
     
       public static void editUser(User user, StringBuilder str,string code)
       {
         code = "VB.NET";
         str = str.Remove(0, 1);
         str.Append("E");
         user.name = "LEE";
    user.age = "10";
    }
      
    static void Main(string[] args)
       {
         string code = "C#";
       User user = new User("Li","23");
         StringBuilder str = new StringBuilder();            
         str.Append("A");            
         editUser(user, str,code);

         Console.WriteLine(code);
         Console.WriteLine(str);
         Console.WriteLine(user.name);
         Console.WriteLine(user.age);
         Console.ReadLine();

       }
    }

    上面代码输如下:

    从上面可以看到string类型的值并没有改变,StringBuilder与class的值都改变了。

  • 相关阅读:
    erlang使用gen_server实现质数服务器(手打代码,还debug了几个错误)
    Java
    某个数组,通过交换使所有奇数都在前半所有偶数都在后半,复杂度O(N)。
    Mybatis映射文件完整模板参照
    Spring集成MyBatis
    jdbc hibernate myBatis比较
    MySQL的简单使用-(一)
    jQuery框架Ajax常用选项
    POI操作Excel的API注意点总结
    Java反射机制练习
  • 原文地址:https://www.cnblogs.com/muyuqianshan/p/6701313.html
Copyright © 2020-2023  润新知