代码之家  ›  专栏  ›  技术社区  ›  L. Guthardt

值和引用类型混淆

  •  2
  • L. Guthardt  · 技术社区  · 9 年前

    在过去的几天里,我在每个网站上都看到了关于这个话题的文章 References and Values Parameter passing

    我理解它是如何工作的,以及你如何使用它,但我不理解每个人都在谈论这个话题。你们大家都这么说 int 是值类型,并且 string 是引用类型。但根据我的理解,类型基本上只取决于它们被声明的类的类型。

    public struct IntHolder
    {
       public int number;
    }
    
    IntHolder first = new IntHolder();
    first.number = 5;
    IntHolder second = first;
    first.number = 6;
    

    现在 second.number 值为5。如果您更改 struct class , number 将像引用类型一样工作,所以这一点都不重要 整数 一串

    显然,声明对象的类的类型决定了其对象的类型,否则我就误解了一个核心概念。请纠正我并帮助我正确理解它,或者告诉我说这句话背后的意义是什么 整数 一串 等…有一个特殊的类型,即使它们初始化的时间无关紧要,所以基本上总是这样。

    1 回复  |  直到 9 年前
        1
  •  8
  •   poke    9 年前

    这与您正在更改的字段类型无关。这里真正相关的只是父类型的类型:

    IntHolder first = new IntHolder();
    IntHolder second = first;
    

    取决于 IntHolder 这有两种不同的影响:

    struct ),这将创建一个 .值类型对象的数据有效 具有

    IntHolder second = new IntHolder();
    second.number = first.number;
    // and all other fields (visible or not) are copied too
    

    已复制 值类型将覆盖该值,而不影响原始对象。这就像局部变量的行为:

    var x = 5;
    var y = 2;
    y = 3; // this does not change x
    

    second = first 。保留值的基础对象对于两者都是相同的。因此,对任一对象的更改都会影响另一个对象,因为没有 另外 :它是由两个独立变量引用的同一个对象。


    我怎么能想象一个 int string 是引用类型吗?我是说 整数 一串 变量就像一个指向字符串对象存储位置的指针?

    这就是为什么例如,将值类型作为方法的参数意味着当调用该方法时,整个值类型对象被复制到堆栈中以执行该方法。

    但是,类型是值类型并不意味着其成员也都是值类型。例如,值类型中字符串成员的实际存储值仍然是对字符串对象的引用。类似地,引用类型的实际内存将包含值类型的实际值,以及对 引用类型的内存位置。

    如果父类型总是比对象类型更重要,我可以使用int和string类型做什么?

    没有什么比另一个更重要了。作为值或引用类型的对象仅影响该对象的存储方式。对于对象的成员,这是完全单独评估的。

    例如,如果您只有一个类和一堆变量,可以将其中一些设置为对另一个变量的引用吗 整数 变量。

    class Test
    {
        private int field;
    
        public void ShowExample()
        {
            // set the value
            field = 12;
    
            // call the method and pass *a reference* to the field
            // note the special syntax
            MutateField(ref field);
    
            // the field, which is a value type, was mutated because it was passed as a reference
            Console.WriteLine(field == 4);
        }
    
        private static void MutateField(ref int value)
        {
            value = 4;
        }
    }