Reference Type in C#

Is object a reference type or value type?

It is a reference type

Doing an example with string isn't very illuminating, because string is also a reference type (as is SampleClass, obviously); your example contains zero "boxing".

if object is reference type then why obj2 value is still "OldString"

Why wouldn't it be? When you create a new string, that doesn't change old references to point at the new string. Consider:

 object obj1 = "OldString";
// create a new string; assign obj1 the reference to that new string "OldString"

object obj2 = obj1;
// copy the reference from obj1 and assign into obj2; obj2 now refers to
// the same string instance

obj1 = "NewString";
// create a new string and assign that new reference to obj1; note we haven't
// changed obj2 - that still points to the original string, "OldString"

Why do we need reference types in .NET

Why do we need reference types in .NET? I can think of only one reason: that it support sharing of data and hence gives storage optimization.

You've answered your own question. Do you need a better reason than that?

Suppose every time you wanted to refer to the book The Hobbit, you had to instead make a copy of the entire text. That is, instead of saying "When I was reading The Hobbit the other day...", you'd have to say "When I was reading In a hole in the ground there lived a hobbit... [all the text] ... Well thank goodness for that, said Bilbo, handing him the tobacco jar. the other day..."

Now suppose every time you used a database in a program, instead of referring to the database, you simply made a full copy of the entire database, every single time you used any of it in any way. How fast do you think such a program would be?

References allow you to write sentences that talk about books by use of their titles instead of their contents. Reference types allow you to write programs that manipulate objects by using small references rather that enormous quantities of data.

string is reference type but why it work as a value type when it's assignment updated

This is a common misunderstanding of the use of references.

s1 is a reference type but its content is a value. You could think all variables are value types, but the way the compiler handles them varies based on value or reference type.

    string s1 = "abc"; 

s1 is equal to the address where "abc" is stored, let's say 0x0000AAAA

    string s2 = s1; 

s2 points to the same address as s1 hence, its value is the same as s1. Both have values 0x000AAAA

    s2 = "123"; 

Strings are immutable, meaning you cannot modify a string, anytime you assign a new value or a modification, you are creating a new string somewhere else in memory while the previous one gets ready for GC, if needed (not in our case actually). At that point, s1 still has value 0x0000AAAA while s2 has a new one 0X0000BBBB.

    Debug.Log(s1 + ":" + s2);

Since both points at different contents, they print different results.

It is only a reference type because the value contained in the variable is not meant to be used as is but is meant to send the pointer to an address location in memory where the actual object is stored.

Except if you use out/ref (the & in C++) then it is implied that the value of the variable is to be used (the address), most likely as a parameter.

Note that this behaviour is the same with any objects, not only string.

Dog dogA = new Dog();
Dog dogB = dogA;
dogA.name = "Wolfie"; // Affect both since we are dereferencing
dogA = new Dog(); // dogA is new object, dogB is still Wolfie

EDIT: OP required explanation on ref/out.

when you want to change an object you would think of the following:

void ChangeObject(GameObject objParam)
{
objParam = new GameObject("Eve");
}

void Start(){
GameObject obj = new GameObject("Adam");
ChangeObject(obj);
Debug.Log(obj.name); // Adam...hold on should be Eve (??!!)
}

ChangeObject gets a GameObejct as parameter, the compiler copies the value contained in obj (00000AAAA) onto objParam, it makes a copy of it and both now have same value.

Within the method, objParam is given a new value and is no more related to the obj outside of the method. objParam is local to the method and is removed on completion (the game object is still in the scene but the reference is lost).

If you wish to change obj within the method:

void ChangeObject(ref GameObject objParam)
{
objParam = new GameObject("Eve");
}

void Start(){
GameObject obj = new GameObject("Adam");
ChangeObject(ref obj);
Debug.Log(obj.name); // Yeah it is Eve !!!
}

this time, it was not the value of obj that is passed but the address of obj. So obj may contain 0x0000AAAA but its own address is 0x0000AABB, then objParam's value is now 0x0000AABB and changing objParam means changing the value stored at 0x0000AABB.

out and ref works the same, only that out requires that a value is assigned within the method, while ref can leave the method without affect the given parameter.

Reference type in C#

Both person and person2 are references, to the same object. But these are different references. So when you are running

person2 = null;

you are changing only reference person2, leaving reference person and the corresponding object unchanged.

I guess the best way to explain this is with a simplified illustration. Here is how the situation looked like before person2 = null:

Before null assignment

And here is the picture after the null assignment:

Sample Image

As you can see, on the second picture person2 references nothing (or null, strictly speaking, since reference nothing and reference to null are different conditions, see comment by Rune FS), while person still references an existing object.

Reference type in struct in C#

The "kind" of type (value/reference) has little to do with how instances are allocated. It's all about life time, and there are more ways to allocate than "heap" and "stack". Read The Truth About Value Types.

But insofar your question makes sense: A struct's member types do not affect how struct instances are allocated, because they do not affect the lifetime of the object. Same goes for classes, by the way.

The member e will be a part of the value type object and allocated where it may be. This member is a reference, and hence any actual Employee object e refers to will be allocated somewhere else1. Though it sounds like one, this is not a special rule; locals and class members and array items behave the same way. It does not defeat the point of value types, rather maintains the benefits of both value and reference types. The value type instances are still separate values instead of being aliased, and they still have simpler and shorter life time allowing better allocation choices with less effort. The reference type instances are still shared and (potentially) long-lived.

1 At least conceptually and in the current implementations; in very simple cases optimizations (escape analysis+allocation sinking) could merge these allocations, but no CLR I'm aware of does that.

In C#, why is String a reference type that behaves like a value type?

Strings aren't value types since they can be huge, and need to be stored on the heap. Value types are (in all implementations of the CLR as of yet) stored on the stack. Stack allocating strings would break all sorts of things: the stack is only 1MB for 32-bit and 4MB for 64-bit, you'd have to box each string, incurring a copy penalty, you couldn't intern strings, and memory usage would balloon, etc...

(Edit: Added clarification about value type storage being an implementation detail, which leads to this situation where we have a type with value sematics not inheriting from System.ValueType. Thanks Ben.)

Is int[] a reference type or a value type?

Arrays are mechanisms that allow you
to treat several items as a single
collection. The Microsoft® .NET Common
Language Runtime (CLR) supports
single-dimensional arrays,
multidimensional arrays, and jagged
arrays (arrays of arrays). All array
types are implicitly derived from
System.Array, which itself is derived
from System.Object. This means that
all arrays are always reference types
which are allocated on the managed
heap, and your app's variable contains
a reference to the array and not the
array itself.

https://msdn.microsoft.com/en-us/library/bb985948.aspx

Reference Type comparison in C#

In .NET, classes are reference types. Reference types has two thing. Object and a reference to object.

In your case, A is a reference to the ObjectA, B is a reference to the ObjectB.

When you define Class1 C = A;

  • First, you create two thing. An object called ObjectC and a reference to the object called C.
  • Then you copy reference of A to reference of C. Now, A and C is reference to the same object.

When you use == with reference objects, if they reference to the same objets, it returns true, otherwise return false.

In your case, that's why B == A and C == B returns false, but if you tried with A == C, it returns true.



Related Topics



Leave a reply



Submit