zoukankan      html  css  js  c++  java
  • string不完全手册

    string 引用类型,,还是值类型 ??

    首先string类型肯定是引用类型,应为它自己继承自object类型,,由于它的特殊性,它有表现了一些值类型的特点. 比如 重载了==, 比较两个字符串的内容,而不是地址

    为什么不将string设置成值类型呢?
    我的理解是:
    string经常要被多个地方用到,如果每个对象保存String的一份Copy,则会消耗大量内存, 而且我们使用string是只关心它的内容,不关心此对象,因此每个对象保存一个它的Copy是没有意义的.

    为什么string很多时候表现出值类型的特点呢?
    我的理解是: 
    1. 重写 equal, 那是因为我们不关心string变量的地址,只关心它的值.
    2. string设计成不变性

    为什么string具有不变性呢?
    我的理解是:
    1.不可改变的一个优点是它是线程安全的。
    2.再者string是最常用来作为集合(Map,Hashtable) 键值得类型,而一旦一个String对象被用作集合的键值,改变String的内容就会破坏集合的语义,造成程序错误。
    3.如果多个string对象引用同一个地址,当其中的某个对象改变时,使得此改变不会影响到其他对象,否则系统很容易rush.
    4.我们一般只关系string的值 

    String作为参数传递的是什么?
    按地址传递,而非值传递.

    public static string staticString = string.Empty;
    static void Main()
    {
                
    string str = "hello, ";
                ChangeString(str);
                Console.WriteLine(String.ReferenceEquals(str, staticString));  
    //output: true
                Console.WriteLine(str);                                        //output: hello, 
                ChangeStringByRef(ref str);
                Console.WriteLine(str);                                        
    //output: hello, world
                Console.ReadLine();
    }


            
    public static void ChangeString(string str)
            
    {
                staticString 
    = str;
                str 
    = str + "world";
            }


            
    public static void ChangeStringByRef(ref string str)
            
    {
                str 
    = str + "world";
            }

    理由:  引用类型按引用传递,值类型按值传递,这些都不错。  【这里表达是有误,引用类型传递的应该是此变量的值,只不过这个变量保存的是引用类型的地址,这是个Pointer,这个不算是引用传递,也叫值传递。 在函数里面拷贝了一份变量的值,指向的仍然是这个引用类型的地址】 [修改于2007年10月24日]
    一个引用类型,比如System.Array类,作为参数向一个方法传递时,传送的是指针,但是这两种代码是不是就意味着等效?
    void Test(Array a)和void Test(ref Array a)结果是并不完全等效。

    如果在函数内部调用构造函数新建了对象并赋予参数,则函数外的变量不会受影响;
    比如a = new ...
    如果只是改动该参数(一个对象)的字段,则会有影响,此时加不加ref都是等效的。
    比如a[i] = ...
    string类型的另外一个特殊性在于它是不会变的,每次操作string,都相当于新建了一个string对象,所以对于string来讲,void Test(String s)void Test(ref String s)永远都是不一样的。在这里string再次表现出了值类型的特点,我们以为这是传值 - 实际上传送的还是地址,但是在操作的时候string被再次初始化,外部根本不能得到这个变化。

    对于变量作用域的概念来讲,微软这么设计也是合理的:既然是函数内部建立的对象,外部就应该没有访问这个对象的能力,函数结束后,这些对象就会被GC收集,同样不会影响外面的程序。

     字符串驻留:

    如果内存上保留多个”Hello”实例,对内存是种浪费.如果在内存中只存储一个”Hello”字符串,并且所有对”Hello”字符串的引用都指向该字符串对象,就会提供内存效率.

    String s = “hello”;
    Object.ReferenceEquals(“hello”, s));    // true;

    CLR初始化时,它会创建一个内部散列表,其中键为字符串,值为指向托管堆中字符串对象的引用.JIT编译时,它会在散列表中查找每一个文本常量字符串.

    如果我们动态创建字符串呢?
     
       string s1 = "Hello";   
        
    string s2 = "Hel";  
        
    string s3 = s2 + "lo";
       
    string s5 = "Hel" + "lo";      
        
    string s4 = string.Intern(s2 + "lo");
       
    Console.WriteLine(object.ReferenceEquals(s1, s3));              //output: False
       
    Console.WriteLine(s1.Equals(s3));                               //output: True
       
    Console.WriteLine(object.ReferenceEquals(s1, s4));              //output: True
       
    Console.WriteLine(object.ReferenceEquals(s1, s5));              //output: True

     因为s3是被动态创建的它并没有添加到CLR内部散列表中.
    垃圾回收器不会释放CLR内部的散列表中引用的字符串对象,只有当整个进程中所有的应用程序域都不再引用这个字符串时,它们才被释放.

    通过字符表达式计算出表达式结果:

            /// <param name="p_str">要计算的字符串表达式,如:"1+3+5"</param>
            public static float Compute(string exp)
            
    {
                
    float rtnValue = 0;
                XmlDocument doc 
    = new XmlDocument();
                XPathNavigator nav 
    = doc.CreateNavigator();
                rtnValue 
    = Convert.ToSingle(nav.Evaluate(exp));
                
    return rtnValue;
            }
  • 相关阅读:
    单元测试
    软件测试计划
    软件杯A9的设计与实现
    阅读笔记7
    阅读笔记6
    阅读笔记5
    阅读笔记4
    阅读笔记3
    阅读笔记2
    阅读笔记1
  • 原文地址:https://www.cnblogs.com/anders06/p/428227.html
Copyright © 2011-2022 走看看