值和引用类型的混淆 [英] Value and Reference types confusion

查看:151
本文介绍了值和引用类型的混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was on every website about this topic and was reading the past few days through Jon Skeets´s article about References and Values and Parameter passing. I understood the concept of those two types, what they stand for and the difference to Value and Reference parameters what is another specification.

我了解这是如何工作的以及如何使用它,但是我不明白有人对这个话题说过什么.大家都说,例如int是值类型,而string是引用类型.但是根据我的理解,类型基本上只取决于声明它们的类的类型.

I understand how this works and how you can use it, but i dont understand something everbody says about this topic. You all out there say that for example int is a value type and string is a reference type. But according to my understanding the type basically just depends on the kind of class in which they got declared.

看看此代码片段以了解我的意思:

Have a look at this code snippet to understand what i mean:

public struct IntHolder
{
   public int number;
}

IntHolder first = new IntHolder();
first.number = 5;
IntHolder second = first;
first.number = 6;

现在second.number的值为5.如果将struct更改为classnumber的作用类似于引用类型,因此int基本上是值类型,这一点都没有关系,它只是关于类的类型.相同的例子适用于string等.

Now second.number has the value 5. If you change struct to class, number will act like a reference type, so it doesnt matter at all that int is in generell a value type, its just about the type of the class. Same example goes for string, etc... .

因此,显然,声明对象的类的类型设置了其对象的类型,或者我误解了一个核心概念.请纠正我并帮助我正确理解它,或者说说int string等具有特殊类型的含义是什么,即使它们初始化时并不重要,因此基本上总是这样.

So apparently the type of the class where the object gets declared sets the type of its objects or i missunderstand a core concept. Please either correct me and help me to understand it correct or tell what is the sense behind saying that int string, etc...has a special type even though it does not matter when they get initialised, so basically always.

推荐答案

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

This has nothing to do with the type of the field you are changing. What is relevant here is indeed just the kind of the parent type:

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

根据IntHolder的种类,有两种不同的效果:

Depending on the kind of IntHolder this has two different effects:

对于值类型(struct),这将创建一个副本.值类型对象的数据与对象一起存在,因此将其全部复制.相当于这样:

For value types (struct), this creates a copy. The data of the value type object lives with the object, so all of it is copied. It’s kind of equivalent to this:

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

这意味着对复制值类型的字段的分配将覆盖该值,而不会影响原始对象.就像本地变量的行为一样:

This means that an assignment to a field of the copied value type will overwrite that value without affecting the original object. It’s like how a local variable behaves:

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

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

However, when the type is a reference type, the assignment second = first just copies the reference. The underlying object where the values are kept are the same for both. So changes to either object affect the other—because there is no "other": it’s the same object that’s just being referenced by two separate variables.

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

To answer the follow-up questions from the comment:

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

How do I need to imagine it that an int variable is a value type and string is a reference type? I mean, so the int variable directly contains the number and the string variable is just like a pointer to a storage location of the string object?

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

Yes, that’s exactly it. The value of a reference is basically just a pointer to the memory where the object actually is, while the value of a value type is the whole object itself.

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

That’s why e.g. having a value type as the parameter to a method means that when the method is called, the whole value type object is copied into the stack for the execution of the method.

作为值类型的类型并不意味着它的成员也将全部为值类型.例如,在值类型内部实际存储的字符串成员的值仍然是对字符串对象的引用.同样,引用类型的实际内存将包含值类型的实际值,以及引用类型的 other 内存位置的引用.

A type being a value type does not mean that its members will all be value types too though. For example, the actually stored value of a string member inside a value type is still a reference to the string object. Similarly, the actual memory for a reference type will contain the actual value for value types, and references to other memory locations for reference types.

如果父类型总是比对象类型重要,那么我可以将int和string类型用于什么呢?

If the parent type always matter more than the objects types, what can I use the type of int and string for?

没有什么比其他更重要的了.对象是值还是引用类型仅影响该对象的存储方式.对于对象的成员,这是完全分开评估的.

There is nothing that matters more than another. An object being a value or a reference type has only implications on how that object is stored. For members of the object, this is evaluated completely separately.

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

不能像值在C中那样具有用于值类型的引用指针.但是您可以引用字段,这些字段使您可以更改值类型的字段的值.例如:

You cannot have a reference pointer for a value type, like you could have in C, no. But you can have references to fields which allow you to mutate the value of fields that are of a value type. For example:

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;
    }
}

这篇关于值和引用类型的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆