简体   繁体   English

C#中的Class和List <>引用类型

[英]Class and List<> Reference Type in c#

I have some doubts in below code regarding CASE 1 and CASE 2, 我在以下有关案例1和案例2的代码中有一些疑问

In CASE-1, we are assigning obj1=null , but in obj2 the copied value is still present as i =10. 在CASE-1中,我们分配的是obj1=null ,但是在obj2中,复制的值仍为i = 10。
In CASE-2, we do something in List , but the value changed in one list is affecting the value in another List . 在CASE-2中,我们在List执行某些操作,但是一个列表中更改的值会影响另一个List的值。

What is the logic behind this as both are reference types. 这背后的逻辑是什么,因为两者都是引用类型。

CASE- 1 情况1

Class A    
{
public int i;
}

A obj1 = new A();
obj1.i =10;

A obj2 = obj1;
obj1 = null;

CASE- 2 案例2

List<int> test1 = new List<int>();
test1.Add(101);

List<int> test2 = test1;
test1.Add(201);

the logic is simple in both: 两者的逻辑都很简单:

both A obj2 and List<int> test2 are reference to the same type as A obj1 and List<int> test1 A obj2List<int> test2都引用与A obj1List<int> test1相同的类型

whhich means that when you perform: 这意味着您执行以下操作时:

Class A    
{
public int i;
}

A obj1 = new A();
obj1.i =10;

A obj2 = obj1;
obj1 = null;

The value of obj2 will be assigned with the value of obj1 but is a object of it's own, it did not become obj1 but rather, just referenced him. obj2的值将被分配为obj1的值,但它是它自己的对象,它没有成为obj1 ,而是引用了他。 obj2 became a new object of type A with the values assigned in obj1 . obj2成为类型为A的新对象,并在obj1分配了值。

When you assign obj1=null then obj2 will not be affected as it's value is already assigned. 当您分配obj1=null obj2将不会受到影响,因为它的值已被分配。

however if you change it to: 但是,如果将其更改为:

obj1 = null;
A obj2 = obj1;

then obj2 will be null, as obj2 is now referencing an empty object. 那么obj2将为null,因为obj2现在正在引用一个空对象。

the same applied in case 2: 情况2的情况相同:

List<int> test2 is referencing List<int> test1 and will be assigned it's value. List<int> test2引用List<int> test1 ,并将为其分配值。 as a result this piece of code: 结果是这段代码:

List<int> test1 = new List<int>();
test1.Add(101);

List<int> test2 = test1;
test1.Add(201);

will produce the following items in test2: 将在test2中产生以下项目:

101
201

you can read further into reference types in this article at Microsoft docs. 您可以在Microsoft文档中进一步阅读本文中的引用类型。 It is pretty extended and covers almost everything. 它相当扩展,几乎涵盖了所有内容。

  1. When you use new keyword at that time some memory is going to allocate and depending on type reference type and value type it get allocation in Heap or may be Stack. 那时使用new关键字时,将要分配一些内存,并且根据类型引用类型和值类型,它会在堆中分配,也可能是堆栈。 ( It is possible that value type may assigned to heap and it entirely depends on CLR) (可能将值类型分配给堆,并且它完全取决于CLR)

  2. Difference between reference type and value type is that reference type hold reference of ( Address of) particular object created in heap. 引用类型和值类型之间的区别在于,引用类型保留对在堆中创建的特定对象的(地址)的引用。 In value type , variable it self hold value. 在值类型中,变量将保留值。

  3. Now in your case 1 A a= new A(); 现在在您的情况下1 A a = new A(); // At this time memory allocated and that allocated memory location address is being assigned to variable a. //此时,已分配的内存和已分配的内存位置地址已分配给变量a。

    A a1 = a; A a1 = a; // At this point new variable a1 is created and that point to same address location in heap as variable a. //此时,将创建新变量a1,该变量指向堆中与变量a相同的地址位置。

    a = null; a = null; // At this point variable a is set to null means it links with actual object allocated is heap get removed. //此时,变量a设置为null意味着它与分配的实际对象的链接是在删除堆之后分配的。

    but a1 still hold the reference so it can access value 但是a1仍然保留引用,因此它可以访问值

  4. In case 2 ( This is also case of reference type) // Your variable test1 and test2 are different but holding same location of address from heap. 在情况2中(这也是引用类型的情况)//您的变量test1和test2不同,但是从堆保存的地址相同。

    // so if you change any item it get affected both variable as both point to same location. //因此,如果您更改任何项目,则两个变量都将指向同一位置,因此会受到影响。

    // Now if you do test1 = null then also test2 to do same thing but you can not access by test1 as it is null now. //现在,如果您执行test1 = null,那么test2也会执行相同的操作,但是您无法通过test1进行访问,因为它现在为null。

CASE-1 情况1

obj1 = null;

reference to the object from obj1 has been removed. obj1对对象的引用已被删除。 The object still exists thanks to obj2 . 由于obj2该对象仍然存在。

CASE-2 CASE-2

Instead 代替

test1 = null;

the method on List<int> is performed: 执行List<int>上的方法:

test1.Add(201);

Both test1 and test2 still point to the same List<int> , so changes in the list are visible. test1test2仍指向同一List<int> ,因此列表中的更改可见。

I think Barr J's answer is a good one, and I'm not sure whether you'll find mine more or less helpful, but this stuff can be confusing enough that I think it's worthwhile to try explaining what's going on in a slightly different way. 我认为Barr J的答案是一个很好的答案,我不确定您是否会找到我的帮助,但是这些东西可能会令人困惑,以至于我认为值得尝试以稍有不同的方式解释正在发生的事情。

A obj1 = new A();  // 1.1
obj1.i = 10;       // 1.2

A obj2 = obj1;     // 1.3
obj1 = null;       // 1.4

On line 1.1, the new operator creates an instance of a reference type A , and the = operator stores a reference to that instance in a variable called obj1 . 在第1.1行上, new运算符创建引用类型A的实例,而=运算符将对该实例的引用存储在名为obj1的变量中。 In order to understand what's going on with your code it's important to distinguish between the reference (the value stored in obj1 ) and the referent (the object to which that value refers, which is stored elsewhere). 为了了解您的代码发生了什么,重要的是要区分引用 (存储在obj1的值)和引用 (该值所引用的对象,该对象存储在其他位置)之间。

On line 1.2, the . 在第1.2行中, . operator serves to dereference the reference stored in obj1 —in other words, to access its referent, the instance of A that you created on line 1.1. 运算符用于取消obj1中存储的引用的引用—换句话说,以访问其引用对象(即您在1.1行创建的A的实例)。 This allows you to access the field i of that instance and assign it a value of 10. 这使您可以访问该实例的字段i并将其分配为10。

Line 1.3 copies the reference stored in obj1 into a second variable called obj2 . 1.3 obj1存储在obj1的引用复制到另一个名为obj2变量中。 You now have two references with the same referent. 现在,您有两个具有相同参照物的参照物。 This means that obj2.i is also equal to 10, because the expressions obj1.i and obj2.i refer to exactly the same value. 这意味着obj2.i也等于10,因为表达式obj1.iobj2.i引用的值完全相同。

Line 1.4 stores the null-reference into obj1 . 1.4 obj1空引用存储到obj1 The crucial difference between lines 1.2 and 1.4 is that there is no dereferencing occurring on line 1.4, so you're not affecting the referent in any way. 1.2和1.4行之间的关键区别在于,在1.4行上没有发生取消引用,因此您不会以任何方式影响引用对象。 All you're doing is replacing a reference to an object with a reference to nothing. 您要做的只是将对对象的引用替换为对任何对象的引用。

Now consider the code from your second example: 现在考虑第二个示例中的代码:

List<int> test1 = new List<int>();  // 2.1
test1.Add(101);                     // 2.2

List<int> test2 = test1;            // 2.3
test1.Add(201);                     // 2.4

Lines 2.1–2.3 are analogous to their counterparts in the first example: they construct an instance of List<int> and two references to that instance, which are stored in two variables of type List<T> called test1 and test2 . 第2.1–2.3行类似于第一个示例中的对应行:它们构造了List<int>的实例和对该实例的两个引用,这些引用存储在List<T>类型的两个变量test1test2 But line 2.4 is different: whereas line 1.4 replaced one reference with another, line 2.4 uses the . 但是第2.4行是不同的:第1.4行将一个引用替换为另一个,而第2.4行则使用. operator again to access the referent of test1 and update its contents. 操作员再次访问test1的引用对象并更新其内容。

You'll see the value 201 in the list regardless of whether you access it by way of the reference stored in test1 or the reference stored in test2 because both references have the same referent; 无论您是通过test1存储的引用还是通过test2存储的引用访问该值,您都将在列表中看到值201,因为这两个引用具有相同的引用; in other words, you have only created a single list. 换句话说,您只创建了一个列表。

obj1 and test1 both are variables of reference type, just like pointers . obj1test1都是引用类型的变量,就像指针一样。 They store references to their data (objects). 他们存储对其数据(对象)的引用 obj1 and obj2 reference the same object but they are different variables. obj1obj2引用相同的对象,但是它们是不同的变量。 So that you assign null to obj1 doesn't change the data (object). 因此,为obj1分配null不会更改数据(对象)。 test1 and test2 are different variables too, but test1.Add and test2.Add call the same method of the same object that they both reference. test1test2也是不同的变量,但是test1.Addtest2.Add调用它们都引用的同一对象的相同方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM