I have some doubts in below code regarding CASE 1 and CASE 2,
In CASE-1, we are assigning obj1=null
, but in obj2 the copied value is still present as i =10.
In CASE-2, we do something in List
, but the value changed in one list is affecting the value in another List
.
What is the logic behind this as both are reference types.
CASE- 1
Class A
{
public int i;
}
A obj1 = new A();
obj1.i =10;
A obj2 = obj1;
obj1 = null;
CASE- 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
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
became a new object of type A
with the values assigned in obj1
.
When you assign obj1=null
then obj2
will not be affected as it's value is already assigned.
however if you change it to:
obj1 = null;
A obj2 = obj1;
then obj2
will be null, as obj2
is now referencing an empty object.
the same applied in case 2:
List<int> test2
is referencing List<int> test1
and will be assigned it's value. 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:
101
201
you can read further into reference types in this article at Microsoft docs. It is pretty extended and covers almost everything.
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. ( It is possible that value type may assigned to heap and it entirely depends on CLR)
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.
Now in your case 1 A a= new A(); // At this time memory allocated and that allocated memory location address is being assigned to variable a.
A a1 = a; // At this point new variable a1 is created and that point to same address location in heap as variable a.
a = null; // At this point variable a is set to null means it links with actual object allocated is heap get removed.
but a1 still hold the reference so it can access value
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.
// 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.
obj1 = null;
reference to the object from obj1
has been removed. The object still exists thanks to obj2
.
Instead
test1 = null;
the method on List<int>
is performed:
test1.Add(201);
Both test1
and test2
still point to the same List<int>
, so changes in the list are visible.
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.
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
. 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).
On line 1.2, the .
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. This allows you to access the field i
of that instance and assign it a value of 10.
Line 1.3 copies the reference stored in obj1
into a second variable called 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.
Line 1.4 stores the null-reference into 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. 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
. But line 2.4 is different: whereas line 1.4 replaced one reference with another, line 2.4 uses the .
operator again to access the referent of test1
and update its contents.
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; in other words, you have only created a single list.
obj1
and test1
both are variables of reference type, just like pointers . They store references to their data (objects). obj1
and obj2
reference the same object but they are different variables. So that you assign null to obj1
doesn't change the data (object). 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.