价值和参考类型混淆

L. *_*rdt 2 c# value-type reference-type

我在每个网站上都有关于这个主题的内容,并且通过Jon Skeets关于参考和值以及参数传递的文章阅读了过去几天.我理解这两种类型的概念,它们代表什么以及与Value和Reference参数的区别是什么是另一种规范.

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

看看这段代码片段,了解我的意思:

public struct IntHolder
{
   public int number;
}

IntHolder first = new IntHolder();
first.number = 5;
IntHolder second = first;
first.number = 6;
Run Code Online (Sandbox Code Playgroud)

现在second.number值为5.如果你struct改为class,number就会像引用类型一样,所以int在generell中根本不是一个值类型,它只是类的类型.同样的例子也适用于string......

显然,声明对象的类的类型设置了对象的类型,或者我错过了一个核心概念.请纠正我并帮助我理解它是正确的,或者告诉我这背后的意义是什么int string......等等......即使它们初始化时无关紧要,所以基本上总是如此.

pok*_*oke 8

这与您要更改的字段类型无关.这里的相关内容实际上只是父类型的类型:

IntHolder first = new IntHolder();
IntHolder second = first;
Run Code Online (Sandbox Code Playgroud)

根据具体IntHolder情况有两种不同的效果:

对于值类型(struct),这将创建一个副本.值类型对象的数据与对象一起存在,因此所有数据都被复制.它有点像这样:

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

这意味着对复制值类型的字段的赋值将覆盖该值而不会影响原始对象.这就像局部变量的行为:

var x = 5;
var y = 2;
y = 3; // this does not change x
Run Code Online (Sandbox Code Playgroud)

但是,当类型是引用类型时,赋值second = first只会复制引用.保存值的基础对象对于两者都是相同的.因此,对任一对象的更改都会影响另一个 - 因为没有"其他":它是由两个单独的变量引用的相同对象.


要回答评论中的后续问题:

我如何想象一个int变量是一个值类型并且string是一个引用类型?我的意思是,所以int变量直接包含数字,string变量就像指向字符串对象存储位置的指针一样?

是的,就是这样.引用的值基本上只是指向对象实际存在的内存的指针,而值类型的值是整个对象本身.

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

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

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

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

是否有可能只有一个类和一堆变量来设置其中一些变量作为对另一个变量的引用,例如int变量.

您不能拥有值类型的引用指针,就像您可以在C中一样,没有.但是,您可以引用允许您改变值类型的字段值的字段.例如:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)