C#中的字符串

1.    值类型与引用类型比较

classProgram

{

    staticvoid Main()

    {

        int a = 9;    //给变量a赋值为9

        int b = a;   //a的副本给变量b

        b = 10;

        Console.WriteLine(string.Format("a={0},b={1}", a, b));

 

        Person ZS = newPerson();       //张三

        ZS.Age = 99;           //张三的年龄是99

        Person SM = ZS;        //三毛等于张三,即张三和三毛就是同一个人

        SM.Age = 100;      //三毛年龄变成100,张三也就变成了100

        Console.WriteLine(string.Format("A={0},B={1}", ZS.Age, SM.Age));

 

        Console.ReadKey();

    }

}

classPerson

{

    publicint Age { get; set; }

}

相同的结构,不同的结果。

 

2.    何以证明string是引用类型

区分值类型与引用类型就是看它是值传递还是引用传递,如下:

using System;

classProgram

{

    staticvoid Main()

    {

        int n = 99;

        Console.WriteLine("Beforen={0}", n.GetHashCode());

        //此时获取到的哈希码值就是n的变量值

        GetInt(n);

 

        string s = "Hello";

        Console.WriteLine("Befores={0}", s.GetHashCode());

        GetString(s);

 

        Console.ReadKey();

    }

 

    staticint GetInt(int n)

    {

        Console.WriteLine("Afterm={0}", n.GetHashCode());

        //传过来的是变量值,说明这是值传递

        return n;

    }

 

    staticstring GetString(string s)

    {

        Console.WriteLine("Afters={0}", s.GetHashCode());

        //传过来的是地址而不"Hello",说明这时引用传递

        return s;

    }

}

 

3.    string是特殊的引用类型

为什么说string是特殊的引用类型,因为看了下面的运行结果你会很困惑,这是怎么回事呢?且看代码分析:

    classProgram

    {

        staticvoid Main()

        {

            string a = "Hello ";

            Console.WriteLine(a.GetHashCode());

            //定义一个变量a,(暂且用哈希码表示地址编号)地址编号为1402305,指向对象的值为“Hello”

 

            string b = a;

            Console.WriteLine(b.GetHashCode());

            //a的地址给b,所以b的地址也是1402305

 

            b = "world";

            Console.WriteLine(b.GetHashCode());

            //string类型的值三只读的,当给他重新赋值的时候需要额外分配内存,同时地址也发生变化。这也就是string类型和一般引用类型的不同之处

            //可以这么理解,字符串变量吃饭用一次性碗筷,这也是为什么在做大量字符串拼接的时候要使用StringBuilder 而不用+=

 

            Console.WriteLine("a:"+a+" b:"+b);

            //此时有两个地址,分别对应托管堆上两个不同的对象值

            Console.ReadKey();

        }

}

运行结果:

 

请思考下面代码的运行结果:

        staticvoid Main()

        {

            string s = "Hello";

            ChangeStr(s);//调用方法  

            Console.WriteLine(s);

        }

        staticvoid ChangeStr(string s){s = "你好!";}

答案:?

   //ChangeStr方法体内传过来的确实是引用地址,但是由于string是只读的,给他重新赋值的时候又重新分配了新地址,而对原来地址和所对应的值没有影响

 

那怎么定义string的值传递方法呢?

staticstring ChangeStr(refstring s)

 

4.    string是一个变态类型

string是特殊的引用类型是出于客气,写到这我就不能不破口大骂string是个变态狂了,Look

classProgram

{

    staticvoid Main()

    {

        string S1 = "Hello";

        string S2 = "Hello";

        bool r1 = object.ReferenceEquals(S1, S2);

 

        var A = new { Age = 12 };   //对象A

        var B = new { Age = 12 };   //对象B

        bool r2 = object.ReferenceEquals(A, B);

 

        Console.WriteLine("r1={0}r2={1}", r1, r2);

        Console.ReadKey();

    }

}

运行结果真的让人出乎意料,同样是引用类型,string总是和别人不一样。

 

消消气,理智一点分析,其实这就是string的内存驻留机制  ,也就是CLRstring做的优化(当有多个字符串变量包含了相同的值时, CLR尽可能不要重复地分配内存,而是让它们统统指向同一个字符串对象实例)。

staticvoid Main()

 {

    string p = "Hello";

    string q = new StringBuilder().Append("Hello").ToString();

    Console.WriteLine(object.ReferenceEquals(p, q));

    //由于声明方式不同,所以CLR不会检查驻留池是否存在相同的变量值

    Console.ReadKey();

 }

 

staticvoid Main()

 {

    string p = "Hello";

    string q = new StringBuilder().Append("Hello").ToString();

    string o = string.Intern(q);  //强制CLR检查驻留池

    Console.WriteLine(object.ReferenceEquals(p, o));

    Console.ReadKey();

 }

                                                                                                         ---- Author:Hollson     QQ:498576940

原文地址:https://www.cnblogs.com/Hollson/p/3276682.html