zoukankan      html  css  js  c++  java
  • 关于string

    string本质上肯定是引用类型,但是这个特殊的类却表现出值类型的特点:

    判断相等性时,是按照内容来判断的,而不是地址

    它肯定是一个引用类型没错,两个方面来看:

    1. class string继承自object,而不是System.ValueType(Int32这样的则是继承于System.ValueType)
    2. string本质上是个char[],而Array是引用类型,并且初始化时也是在托管堆分配内存的

    微软设计这个类的时候估计是为了方便操作,所以重写了操作符和Equals方法,不然的话我们判断string相等得这样:

    foreach(char c in s.ToCharArray()){...}

    但是另外一个常用的对象微软却没有帮忙重写等值判断的方法:Array

    这样int[] a = {1,2,3}和int b = {1,2,3},a == b?// false

    还有一个容易搞错的地方是按引用传递还是按值传递的问题:

    引用类型按引用传递,值类型按值传递,这些都不错。
    一个引用类型,比如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收集,同样不会影响外面的程序。

    ----

    另外一个介绍

    using System;
    using System.Collections.Generic;

    public class MyClass
    {
        
    public static void Main()
        
    {
            
    string s="abc";
            
    string a=s;
            s
    ="def";
            Console.WriteLine(
    "{0},{1}",a,s);
        }
        
    }

    输出的是abc,def
    我们都知道数组是引用类型的,请看一下段代码:

    using System;
    class MyClass
    {
        
    static void Main()
        {
            
    int [] Arr1={1,2,3,4,5};
            
    int [] Arr2=Arr1;
            Arr1[
    1=200;
            
    foreach (int i in Arr2)
            Console.WriteLine(i);
        }
    }


    我们都知道值类型如果附值的时候,是把自己的一个副本附给另一个变量,之后它们互不影响。而引用类型则是把它在堆栈中的地址复制一份给另一个变量,它们的指向仍是一样的,所以当对一个变量进行操作的时候会影响到另外一个变量,所以上例中Arr2[1]=200而不是2。所以我们可以暂且认为string是值类型。
    下面的一段代码再一次说明了它具有值类型的特征。

    using System;
    class MyClass
    {
        
    static void M(string s)
        {
            s
    ="abcd";
        }
        
    static void Main()
        {
            
    string s="efgh";
            M(s);
            Console.WriteLine(s);
        }
    }


    但实际上string是引用类型的(sorry,我水平有限,没办法证明),引用一下MSDN上的话:“String 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了 String 对象的方法实际上是返回一个包含修改内容的新 String 对象。”
    大家看了这句话是不是有种恍然大悟的感觉了?让我把它说的更通俗点吧“重新赋值,就是在堆中重新分一块内存给它放新的值即重新NEW了一个对象,而不是覆盖原先的值是.而原先的值将等着CG来回收。
    那如果你想定义经常变的字符串,用string类的话,如果CG不能够及时回收,那不是很占用内存吗?
    所以MS推荐了另一个类:System.Text.StringBuilder 类.

     具有值类型特征的操作

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

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

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

    总结:

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

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

  • 相关阅读:
    小程序全局生命周期( 仅供了解 )
    iview表格render小案例2
    iview中表格根据条件渲染
    如何实现页面同时在移动端和pc端的兼容问题
    小程序页面中的生命周期( 仅供了解 )
    弹性盒基本属性
    elementUI实现分页效果+模糊搜索效果
    事件流 ---- 事件冒泡与事件捕获
    React生命周期
    数据库索引数据结构btree,b-tree和b+tree树
  • 原文地址:https://www.cnblogs.com/gsk99/p/2024587.html
Copyright © 2011-2022 走看看