

Dániel Szabó
Value and reference type assignment in c#.
- Mar 5, 2020
- 4,514 View s
Introduction
Types and context, value and reference, reference type.
When it comes to the type system of a programming language, there are two main categories: strongly and weakly typed programming languages. These categories define how typing rules apply during compilation and runtime of the source code. In 1974, Barbara Liskov and Stephen Zilles defined the strongly typed programming language this way.
Whenever an object is passed from a calling function to a called function, its type must be compatible with the type declared in the called function.
In this guide we will explore why C# falls into the category of strongly typed languages and how this affects type assignment, particularly when it comes to value and reference types.
In the .NET framework, and thus the C# programming language, there are two main types: value type and reference type. There are also two contexts in C#, safe and unsafe . It should be mentioned that in an unsafe context, we have a third type called pointer . For now it's enough to know that we call a context safe when the code is running under the supervision of the CLR, and unsafe code is quite the opposite.
There are four types that fall to the reference type category:
The rest of the types fall to the value type category:
Let's look at a demonstration of the value type. In this code, we have a function that takes a value of double type and squares it.
The output looks like this if we pass 22.22 as input for the function.
What happens behind the scenes? The value of d 's content is allocated on the stack. A single space in memory based on the type is reserved in memory, and this variable directly holds the value. If we were to copy this value to another variable via an assignment, the value would be copied so you would have the value of d reserved twice on the stack, one for each variable. Every predefined datatype, including enums and even structs, works this way. The value types are created at compile time and because of this, they are protected from the garbage collector—it cannot access them.
Let's look at a demonstration for this, too, and then dissect it.
The output looks like this:
We have a class which is of reference type. This is important to note because the function called initializeServer , which is initializing it, takes two arguments. The first one is of value type, and the second one is of reference type, which is where the class is passed. The function will change public properties of the class passed by reference based on the category we pass. If we pass a category that is not implemented, an error is thrown with this message:
What happens behind the scenes? The server class instances a, b, and c are of reference type. This means when we pass them to the initializeServer function, their addresses are passed rather than the instance with the data. When we assign a reference variable to another, we do not copy the data. We simply tell that the new variable also references the original address. This means if we were to modify either of them, the change would be reflected on both since they point to the same location in memory. The reference type variables are stored in a designated space in memory called heap. As a result, when such a variable is not used anymore in our application, it is subject to be released by the garbage collector.
A note on stack vs. heap: Stack is used for static memory allocation, while heap is used for dynamic memory allocation. They are both useful, but they are intended for different purposes.
In this guide, we looked at value and reference types. Through several examples, we dissected what these types are for and how they are different programmatically. We also learned that there are two main memory types for C#. I hope this guide has been informative to you and I would like to thank you for reading it.
- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- About the company
Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
C# Reference type assignment VS value type assignment
I understand the theoretical concept that assigning one reference type variable to another, only the reference is copied, not the object. assigning one value type variable to another, the object is copied. But I cannot spot the different in the code. would someone kindly point out the difference between the following two code blocks? Thank you!
REFERENCE TYPE ASSIGNMENT
VALUE TYPE ASSIGNMENT
- 2 The output is as it should be. So, what is the question? – shahkalpesh Aug 2, 2009 at 19:54
- As per the example, it is only the 3rd point where it is different. Changing one of the references will affect other instances referring to it. It won't be the case in value type. – shahkalpesh Aug 2, 2009 at 19:56
- This would be a lot clearer if you'd used the same terms in both blocks of code. – Tim Long Aug 2, 2009 at 20:09
6 Answers 6
Well, the obvious difference is that with the class example, it appears both joe and bob changed in the last part there, to the same value.
In the struct example, they keep their separate values, simply because each variable is a whole struct value by itself, not just a reference to a common object in memory somewhere.
The main code-wise difference being the type you use, class or struct , this dictates whether you're creating a reference type or a value type.
- That's it? Which is which!?! At least say that much or offer a link... ._. – Paul-Sebastian Manole Jan 25, 2013 at 12:20
One is a structure and the other is a class. This seems like an overly complicated example involving more than just value and reference differences but the differences between classes and structs as well.
When one struct is assigned to another a copy is made. When one class is assigned to another only the reference changes.
//Reference Type
The first code snippet contains Employee which is a class and in the second one, Employee is a struct
To see the difference more clearly, try something like
// assign joe reference value to bob variable
And do something similar in the reference-type example.
You will be able to demonstrate that in the second examples there are two different instances of Height, while in the first example there is only one (shared) instance of Employee.

On my system, those two code blocks produce the following output:
Original Employee Values:
joe = Joe bob = Bob Values After Reference Assignment: joe = Joe bob = Joe Values After Changing One Instance: joe = Bobbi Jo bob = Bobbi Jo
Original Height Values: joe = 71 bob = 59 Values After Value Assignment: joe = 71 bob = 71 Values After Changing One Instance: joe = 65 bob = 71
The difference seems self-evident. In the first sample, changing one of the values affects both references, because they are both referencing the same underlying object. In the second sample, changing one of the objects affects only that object, because when value types are copied, each object receives it own private copy. When you say bob = joe; in the second sample, you;re not assigning a reference (the comment is misleading). What you're doing is creating a new instance of the Height struct, copying all the values from joe and storing the new object as bob.
Your Answer
Sign up or log in, post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service , privacy policy and cookie policy
Not the answer you're looking for? Browse other questions tagged c# or ask your own question .
- The Overflow Blog
- How Intuit democratizes AI development across teams through reusability sponsored post
- The nature of simulating nature: A Q&A with IBM Quantum researcher Dr. Jamie...
- Featured on Meta
- We've added a "Necessary cookies only" option to the cookie consent popup
- Launching the CI/CD and R Collectives and community editing features for...
- Staging Ground Beta 1 Recap, and Reviewers needed for Beta 2
- The [amazon] tag is being burninated
- Temporary policy: ChatGPT is banned
Hot Network Questions
- Calculating probabilities from d6 dice pool (Degenesis rules for botches and triggers)
- How do I align things in the following tabular environment?
- How can I detect that \centering is in effect?
- better way to photograph a LED wall (people dancing in front of it)
- What can a lawyer do if the client wants him to be acquitted of everything despite serious evidence?
- Can I tell police to wait and call a lawyer when served with a search warrant?
- What's the difference between a power rail and a signal line?
- Transgenic Peach DNA Splicing
- What sort of strategies would a medieval military use against a fantasy giant?
- Finite abelian groups with fewer automorphisms than a subgroup
- Who owns code in a GitHub organization?
- Is it suspicious or odd to stand by the gate of a GA airport watching the planes?
- Is it correct to use "the" before "materials used in making buildings are"?
- Why are trials on "Law & Order" in the New York Supreme Court?
- If you preorder a special airline meal (e.g. vegan) just to try it, does this inconvenience the caterers and staff?
- Do roots of these polynomials approach the negative of the Euler-Mascheroni constant?
- Did any DOS compatibility layers exist for any UNIX-like systems before DOS started to become outmoded?
- What did Ctrl+NumLock do?
- About an argument in Famine, Affluence and Morality
- Why are non-Western countries siding with China in the UN?
- What is pictured in this SHERLOC camera?
- Confusion About Entropy
- How can I explain to my manager that a project he wishes to undertake cannot be performed by the team?
- Why is this sentence from The Great Gatsby grammatical?
Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Reference types (C# reference)
- 2 minutes to read
- 12 contributors
There are two kinds of types in C#: reference types and value types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data. With reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable. With value types, each variable has its own copy of the data, and it's not possible for operations on one variable to affect the other (except in the case of in , ref , and out parameter variables; see in , ref , and out parameter modifier).
The following keywords are used to declare reference types:
C# also provides the following built-in reference types:
- C# reference
- C# keywords
- Pointer types
- Value types
Submit and view feedback for
Additional resources

Value Type and Reference Type
In C#, these data types are categorized based on how they store their value in the memory. C# includes the following categories of data types:
- Reference type
- Pointer type
A data type is a value type if it holds a data value within its own memory space. It means the variables of these data types directly contain values.

For example, consider integer variable int i = 100;
The system stores 100 in the memory space allocated for the variable i . The following image illustrates how 100 is stored at some hypothetical location in the memory (0x239110) for 'i':

The following data types are all of value type:
Passing Value Type Variables
When you pass a value-type variable from one method to another, the system creates a separate copy of a variable in another method. If value got changed in the one method, it wouldn't affect the variable in another method.
In the above example, variable i in the Main() method remains unchanged even after we pass it to the ChangeValue() method and change it's value there.
Reference Type
Unlike value types, a reference type doesn't store its value directly. Instead, it stores the address where the value is being stored. In other words, a reference type contains a pointer to another memory location that holds the data.
For example, consider the following string variable:
string s = "Hello World!!";
The following image shows how the system allocates the memory for the above string variable.

As you can see in the above image, the system selects a random location in memory (0x803200) for the variable s . The value of a variable s is 0x600000 , which is the memory address of the actual data value. Thus, reference type stores the address of the location where the actual value is stored instead of the value itself.
The followings are reference type data types:
- Arrays (even if their elements are value types)
Passing Reference Type Variables
When you pass a reference type variable from one method to another, it doesn't create a new copy; instead, it passes the variable's address. So, If we change the value of a variable in a method, it will also be reflected in the calling method.
In the above example, we pass the Student object std1 to the ChangeReferenceType() method. Here, it actually pass the memory address of std1 . Thus, when the ChangeReferenceType() method changes StudentName , it is actually changing StudentName of std1 object, because std1 and std2 are both pointing to the same address in memory.
String is a reference type, but it is immutable. It means once we assigned a value, it cannot be changed. If we change a string value, then the compiler creates a new string object in the memory and point a variable to the new memory location. So, passing a string value to a function will create a new variable in the memory, and any change in the value in the function will not be reflected in the original value, as shown below.
The default value of a reference type variable is null when they are not initialized. Null means not refering to any object.

A value type variable cannot be null because it holds value, not a memory address. C# 2.0 introduced nullable types , using which you can assign null to a value type variable or declare a value type variable without assigning a value to it.
- Static vs Singleton in C#
- Difference between == and Equals() Method in C#
- Asynchronous programming with async, await, Task in C#
- How to loop through an enum in C#?
- Generate Random Numbers in C#
- Difference between Two Dates in C#
- Convert int to enum in C#
- BigInteger Data Type in C#
- Convert String to Enum in C#
- Convert an Object to JSON in C#
- Convert JSON String to Object in C#
- DateTime Formats in C#
- How to convert date object to string in C#?
- Compare strings in C#
- How to count elements in C# array?
- Difference between String and string in C#.
- How to get a comma separated string from an array in C#?
- Boxing and Unboxing in C#
- How to convert string to int in C#?
- More C# articles
- C# Questions & Answers
- C# Skill Test
- C# Latest Articles
Value and reference types in C#
Jan 30, 2016 • Carlos Schults • Tags: csharp beginners oop type system

This is my first “real” post here on my blog, and I decided to talk about value types and reference types. This is somewhat of a basic subject, in the sense that it is something that you should already know if you write C# code for a living.But at the same time, it can be a little non-intuitive if you’re not an experienced developer. I’ll try to make this as simple and short as possible, so I won’t talk about string immutability, boxing, unboxing, and some other things with fancy names. I’ll write about those in the future, but for today let’s focus on the basics.
So, take a look at the following piece of code.
No surprises here, cause this is the exact behaviour you’d expect. Now, suppose we have a class like this:
Now, you do this:
Now is the time when beginners sometimes get confused. “This doesn’t make sense”, they say. “I’ve changed the value of one of the variables, and the other also changed.”
Well, that is the wrong way to look at it. As it turns out, you didn’t really change the value of the variable , in this case. And that’s the point.
Remember the first example? Let’s take a look at it again, this time step by step:

We declare the first variable and assign the value 10 to it. Now, somewhere inside the computer’s memory, there is a “box” labeled “x” which holds the value 10.

We declare the second variable and assign the value of the first variable to it. Notice that the value is copied from x to y. Now we have two boxes, one labeled x, the other labeled y, and both of them hold the value 10.

Finally, we increment the value of the variable y by 1. Notice that the value of x remained unchanged. Of course, because they have nothing to do with each other!
On the other hand, something very different happens when you’re dealing with reference types. To understand that, let’s review the second example, step by step:

First, we create a variable called person and assign to it a new instance of the Person class. Now, somewhere inside the computer’s memory, we have a box called “person”. Notice, however, that our variable person stores a reference that points to the instance of Person, instead of storing the instance itself!

In the second step, we create a variable called person2 and assign the value of the variable person to it. As in the previous example, the value from one variable is copied to the other. In this case, the value that is copied is the reference that points to the instance . So now we have two variables whose values are references that point to the same instance of Person.
Now, of course when you change the object’s data (e.g. alter the person’s name and/or profession), it seems that the two variables were altered. In fact, the variables’s values remain exactly the same: what was really changed was the object to which they point to.
So, we could summarize that way: value types store data. When you assign the value of a value type variable to another, what gets copied is the data itself (like an integer, for example). This is similar to when you copy a file from one folder and paste it somewhere else. You made a copy, but from now on, they are independent files and have nothing to do with each other.
Reference types store a reference, that points to the data, which lives somewhere else in the machine’s memory. When you assign the value of a reference type variable to another, what gets copied is the reference.It can be useful to think of them as shortcuts to files. If you have one or more shortcuts that point to a particular file, when you make changes in the original file, those changes will be visible through the shortcuts. Because they’re just that, shortcuts.
Which types are value types?
According to MSDN, the value types are:
- All numeric data types
- Boolean, Char, and Date
- All structures
- Enumerations
Which types are reference types?
Again, acording to MSDN:
Wait a minute! String is a reference type?!
Maybe you’re surprised to see String listed as a reference type. After all, it seems to behave as a value type. Well, the reason for this is because String is an immutable type . As I said, I won’t talk about this today, but soon we’ll have a post all about System.String.
OK, that’s it for today. I hope you guys enjoyed this post, and I’d love to hear your feedback.Have I expressed myself clearly enough? Have I said something innacurate - or even flat-out wrong? Let me know in the comments, or reach me on twitter .
References:
- https://jonskeet.uk/csharp/references.html
- https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
With reference types, however, an object is created in memory, and then handled through a separate reference—rather like a pointer. Suppose Point is a struct, and Form is a class. We can instantiate each as follows:
Point p1 = new Point(); // Point is a *struct* Form f1 = new Form(); // Form is a *class*
In the first case, one space in memory is allocated for p1 , wheras in the second case, two spaces are allocated: one for a Form object and another for its reference ( f1 ). It's clearer when we go about it the long way:
Form f1; // Allocate the reference f1 = new Form(); // Allocate the object
If we copy the objects to new variables:
Point p2 = p1; Form f2 = f1;
p2 , being a struct, becomes an independent copy of p1 , with its own separate fields. But in the case of f2 , all we’ve copied is a reference , with the result that both f1 and f2 point to the same object.
This is of particular interest when passing parameters to methods. In C#, parameters are (by default) passed by value, meaning that they are implicitly copied when passed to the method. For value-type parameters, this means physically copying the instance (in the same way p2 was copied), while for reference-types it means copying a reference (in the same way f2 was copied). Here is an example:
Point myPoint = new Point (0, 0); // a new value-type variable Form myForm = new Form(); // a new reference-type variable
Test (myPoint, myForm); // Test is a method defined below
void Test (Point p, Form f)
{ p.X = 100; // No effect on MyPoint since p is a copy f.Text = "Hello, World!"; // This will change myForm’s caption since // myForm and f point to the same object f = null; // No effect on myForm }
Assigning null to f has no effect because f is a copy of a reference, and we’ve only erased the copy.
We can change the way parameters are marshalled with the ref modifier. When passing by “reference”, the method interacts directly with the caller’s arguments. In the example below, you can think of the parameters p and f being replaced by myPoint and myForm :
Test ( ref myPoint, ref myForm); // pass myPoint and myForm by reference
void Test ( ref Point p, ref Form f)
{ p.X = 100; // This will change myPoint’s position f.Text = “Hello, World!”; // This will change MyForm’s caption f = null ; // This will nuke the myForm variable! }
In this case, assigning null to f also makes myForm null, because this time we’re dealing with the original reference variable and not a copy of it.

Memory Allocation
The Common Language Runtime allocates memory for objects in two places: the stack and the heap . The stack is a simple first-in last-out memory structure, and is highly efficient. When a method is invoked, the CLR bookmarks the top of the stack. The method then pushes data onto the stack as it executes. When the method completes, the CLR just resets the stack to its previous bookmark—“popping” all the method’s memory allocations is one simple operation!
In contrast, the heap can be pictured as a random jumble of objects. Its advantage is that it allows objects to be allocated or deallocated in a random order. As we’ll see later, the heap requires the overhead of a memory manager and garbage collector to keep things in order.
To illustrate how the stack and heap are used, consider the following method:
void CreateNewTextBox() { TextBox myTextBox = new TextBox(); // TextBox is a class }
In this method, we create a local variable that references an object. The local variable is stored on the stack, while the object itself is stored on the heap:
The stack is always used to store the following two things:
- The reference portion of reference-typed local variables and parameters (such as the myTextBox reference )
- Value-typed local variables and method parameters (structs, as well as integer s, bool s, char s, DateTime s, etc.)
The following data is stored on the heap:
- The content of reference-type objects.
- Anything structured inside a reference-type object.
Memory Disposal
Once CreateNewTextBox has finished running, its local stack-allocated variable, myTextBox , will disappear from scope and be “popped” off the stack. However, what will happen to the now-orphaned object on the heap to which it was pointing? The answer is that we can ignore it—the Common Language Runtime’s garbage collector will catch up with it some time later and automatically deallocate it from the heap. The garbage collector will know to delete it, because the object has no valid referee (one whose chain of reference originates back to a stack-allocated object). [1] C++ programmers may be a bit uncomfortable with this and may want to delete the object anyway (just to be sure!) but in fact there is no way to delete the object explicitly. We have to rely on the CLR for memory disposal—and indeed, the whole .NET framework does just that!
However there is a caveat on automatic destruction. Objects that have allocated resources other than memory (in particular “handles”, such as Windows handles, file handles and SQL handles) need to be told explicitly to release those resources when the object is no longer required. This includes all Windows controls, since they all own Windows handles! You might ask, why not put the code to release those resources in the object’s finalizer? (A finalizer is a method that the CLR runs just prior to an object’s destruction). The main reason is that the garbage collector is concerned with memory issues and not resource issues. So on a PC with a few gigabytes of free memory, the garbage collector may wait an hour or two before even getting out of bed!
So how do we get our textbox to release that Windows handle and disappear off the screen when we’re done with it? Well, first, our example was pretty artificial. In reality, we would have put the textbox control on a form in order to make it visible it in the first place. Assuming myForm was created earlier on, and is still in scope, this is what we’d typically do:
myForm.Controls.Add (myTextBox);
As well as making the control visible, this would also give it another referee (myForm.Controls). This means that when the local reference variable myTextBox drops out of scope, there’s no danger of the textbox becoming eligible for garbage collection. The other effect of adding it to the Controls collection is that the .NET framework will deterministically call a method called Dispose on all of its members the instant they’re no longer needed. And in this Dispose method, the control can release its Windows handle, as well as dropping the textbox off the screen.
All classes that implement IDisposable (including all Windows Forms controls) have a Dispose method. This method must be called when an object is no longer needed in order to release resources other than memory. There are two ways this happens: - manually (by calling Dispose explicitly) - automatically: by adding the object to a .NET container, such as a Form , Panel , TabPage or UserControl . The container will ensure that when it’s disposed, so are all of its members. Of course, the container itself must be disposed (or in turn, be part of another container). In the case of Windows Forms controls, we nearly always add them to a container – and hence rely on automatic disposal.
The same thing applies to classes such as FileStream —these need to be disposed too. Fortunately, C# provides a shortcut for calling Dispose on such objects, in a robust fashion: the using statement:
using (Stream s = File.Create ("myfile.txt"))
This translates to the following code:
Stream s = File.Create ("myfile.txt");
if (s != null) s.Dispose();
The finally block ensurse that Dispose still gets executed should an exception be thrown within the main code block.
What about in WPF?
Most of the elements in WPF don’t wrap unmanaged handles requiring explicit disposal. So you can mostly ignore the disposal with WPF!
A Windows Forms Example
Let's look a couple more types you’ll come across often in Windows Forms applications. Size is a type used for representing a 2-dimensional extent and Font , as you would expect, encapsulates a font and its properties. You can find them in the .NET framework, in the System.Drawing namespace. The Size type is a struct—rather like Point , while the Font type is a class. We'll create an object of each type:
Size s = new Size (100, 100); // struct = value type Font f = new Font (“Arial”,10); // class = reference type
and we’ll also create a form. Form is a class in System.Windows.Forms namespace, and is hence a reference type:
Form myForm = new Form();
To set the form's size and font, we can assign the objects s and f to the form via its properties:
myForm.Size = s; myForm.Font = f;
Don't get confused by the double usage of the identifiers Size and Font : now they are referring to members of myForm and not the Size and Font classes. This double usage is acceptable in C# and is applied extensively throughout the .NET framework.
Here's what it now looks like in memory:
As you can see, with s , we've copied over its contents , while in the case of f , we've copied over its reference (resulting in two pointers in memory to the same Font object). This means that changes made via s will not affect the form, while changes made via f , will [2] .
In-Line Allocation
Previously we said that for value-typed local variables, memory is allocated on the stack. So does that mean the newly copied Size struct is also allocated on the stack? The answer is no , because it’s not a local variable! Instead, it’s stored in a field of another object (in this case a form) that’s allocated on the heap. Therefore, it must, too, be allocated on the heap. This mode of storage is called "in-line".
Fun with Structs
We've made a slightly simplifying assumption in the diagrams in that Size and Font are depicted as fields in the Form class. More accurately, they are properties, which are facades for internal representations we don’t get to see. We can imagine their definitions look something like this:
class Form { // Private field members
Size size; Font font;
// Public property definitions
public Size Size { get { return size; } set { size = value ; fire resizing events } }
public Font Font { get { return font; } set { font = value ; } } }
By using properties, the class has an opportunity to fire events when the form’s size or font changes. It provides further flexibility in that other size-related properties, such as ClientSize (the size of a control’s internal area without title bar, borders, or scroll bars) can work in tandem with the same private fields.
But there is a snag. Suppose we want to double the form’s height, through one of its properties. It would seem reasonable to do this :
myForm.ClientSize.Height = myForm.ClientSize.Height * 2;
or more simply:
myForm.ClientSize.Height *= 2;
However, this generates a compiler error:
Cannot modify the return value of 'System.Windows.Forms.Form.ClientSize' because it is not a variable
We get the same problem whether we use Size or ClientSize. Let’s look at why.
Imagine ClientSize as a public field rather than a property. The expression myForm.ClientSize.Height would then simply reach through the membership hierarchy in a single step and access the Height member as expected. But since ClientSize is a property, myForm.ClientSize is first evaluated (using the property’s get method), returning an object of type Size . And because Size is a struct (and hence a value-type) what we get back is a copy of the form’s size. And it’s this copy whose size we double! C# realizes our mistake, and generates an error rather than compiling something that it knows won’t work. (Had Size been defined instead as a class, there would have been no problem, since ClientSize ’s get accessor would have returned a reference, giving us access to the form’s real Size object.)
So how then do we change the form’s size? You have to assign it a whole new object:
myForm.ClientSize = new Size (myForm.ClientSize.Width, myForm.ClientSize.Height * 2);
There’s more good news in that with most controls we usually size them via their external measurements ( Size rather than ClientSize ) and for these we also have ordinary integer Width and Height properties that we can get and set!
You might wonder if they could they have saved all this bother by defining Size as a class rather than a struct. But if Size was a class, its Height and Width properties would probably have been made read-only to avoid the complication of having to raise events whenever their values changed (so that the control can know to resize itself). And as read-only properties, you would be forced to go about changing them by creating a new object—so we’d be back to square one!

- An Interview Question
- TECHNOLOGIES
- INTERVIEW PREP

C# Concepts - Value Type And Reference Type

- Vishal Verma
- Mar 31, 2022
- Other Artcile
This article explains C# concepts of Value and Reference types.
This seems to be a basic but very important part of C# programming.
Value types are generally (not always) stored on the stack and are passed by copying.
The way in which a variable assignment works differs between reference and value types.
If we have something like:
Implementation
Here, both v1 and v2 will be on the stack and are different entities.
- Reference Type
A value type is basically stored on the heap and passed by creating a reference.
v1 and v2 will be on the heap as two entities until a breakpoint.
And after the breakpoint, they both point to one entity.

Figure 1: BreakPoin1

Figure 2: BreakPoint2
So, a change in one will affect the other.
Once you pass a value type, you pass a copy to the other method.
But what if we want to change it? Use the “ref” keyword for that.
The difference between ref and out should be studied (I will try to write another article for that topic).
Use of ref in value types
The ref keyword passes the value by reference (details to be explained later).
Now, v1 becomes 100 because both share the same reference (one entity).
Passing Arguments
We have the following four possibilities:
- Pass value type by value.
- pass value type by reference
- pass reference type by value.
- pass reference type by reference.
Pass value type by value
10 (because one more copy is created and thus the original is not affected).
Pass value type by reference
0 (since now one copy is shared by both methods).
Pass reference type by value (by default)
10 (this happens because we are passing it by value).
Now here if we do, obj.val=100 then it will print 100 (this is because passing a variable to a function by value is equivalent to instantiating a new variable and assigning it to the first).
More to be discussed in the section on shallow copy vs deep copy (in a later article).
Pass reference type by reference
The error we have now is obj=null so it will give a nullobject error.
Disclaimer - I got inspiration from JonSkeet and various other talented guys.
- concepts of C#

Beginning C# Object Oriented Programming
Featured articles.

Reference Types and Value Types
Data types in C# come in two distinct flavors: value types and reference types . In order to understand the distinction, it helps to consider how space is allocated in C#. Whenever a method is called, the space needed to execute that method is allocated from a data structure known as the call stack . The space for a method includes its local variables, including its parameters (except for out or ref parameters ). The organization of the call stack is shown in the following figure:

When the currently-running method makes a method call, space for that method is taken from the beginning of the unused stack space. When the currently-running method returns, its space is returned to the unused space. Thus, the call stack works like the array-based implementation of a stack , and this storage allocation is quite efficient.
What is stored in the space allocated for a variable depends on whether the variable is for a value type or a reference type. For a value type, the value of the variable is stored directly in the space allocated for it. There are two kinds of value types: structures and enumerations . Examples of structures include numeric types such as int , double , and char . An example of an enumeration is DialogResult (see " MessageBox es" and “File Dialogs” ).
Because value types are stored directly in variables, whenever a value is assigned to a variable of a value type, the entire value must be written to the variable. For performance reasons, value types therefore should be fairly small.
For reference types, the values are not stored directly into the space allocated for the variable. Instead, the variable stores a reference , which is like an address where the value of the variable can actually be found. When a reference type is constructed with a new expression, space for that instance is allocated from a large data structure called the heap (which is unrelated to a heap used to implement a priority queue ). Essentially, the heap is a large pool of available memory from which space of different sizes may be allocated at any time. We will not go into detail about how the heap is implemented, but suffice it to say that it is more complicated and less efficient than the stack. When space for a reference type is allocated from the heap, a reference to that space is stored in the variable. Larger data types are more efficiently implemented as reference types because an assignment to a variable of a reference type only needs to write a reference, not the entire data value.
There are three kinds of reference types: classes, interfaces , and delegates . Delegates are used to represent individual methods, and are beyond the scope of this course.
Variables of a reference type do not need to refer to any data value. In this case, they store a value of null (variables of a value type cannot store null ). Any attempt to access a method, property, or other member of a null or to apply an index to it will result in a NullReferenceException .
The fields of classes or structures are stored in a similar way, depending on whether the field is a value type or a reference type. If it is a value type, the value is stored directly in the field, regardless of whether that field belongs to an object allocated from the stack or the heap. If it is a reference type, it stores either null or a reference to an object allocated from the heap.
The difference between value types and reference types can be illustrated with the following code example:
Suppose this method is called as follows:
The method contains six local variables: i , j , a , b , c , and d . int is a structure, and hence a value type. Point is a structure (and hence a value type) containing public int properties X and Y , each of which can be read or modified. int[ ] , however, is a reference type. Space for all six of these variables is allocated from the stack, and the space for the two Point s includes space to store two int fields for each. The values 1 and 2 passed for i and j , respectively, are stored directly in these variables.
The constructor in the first line of the method above sets the X property of a to 1 and the Y property of a to 2. The next statement simply copies the value of a - i.e., the point (1, 2) - to b . Thus, when the X property of a is then changed to 3, b is unchanged - it still contains the point (1, 2).
On the other hand, consider what happens when something similar is done with array variables. When c is constructed, it is assigned a new array allocated from the heap and containing 10 locations. These 10 locations are automatically initialized to 0. However, because an array is a reference type, the variable c contains a reference to the actual array object, not the array itself. Thus, when c is copied to d , the array itself is not copied - the reference to the array is copied. Consequently, d and c now refer to the same array object, not two different arrays that look the same. Hence, after we assign c[0] a value of 1, d[0] will also contain a value of 1 because c and d refer to the same array object. (If we want c and d to refer to different array objects, we need to construct a new array for each variable and make sure each location of each array contains the value we want.) The array returned therefore resides on the heap, and contains 1 at index 0, and 0 at each of its other nine locations. The six local variables are returned to unused stack space; however, because the array was allocated from the heap, the calling code may continue to use it.
Because classes are reference types, it is possible for the definition of a class C to contain one or more fields of type C ; for example:
Such circularity would be impossible for a value type because there would not be room for anything else if we tried to include a value of type C within a value of type C . However, because C is a class, and hence a reference type, _nextC simply contains a reference to some object of type C . When the runtime system constructs an instance of type C , it just needs to make it large enough to hold a reference, along with any other fields defined within C . Such recursive definitions are a powerful way to link together many instances of a type. See “ Linked Lists ” and “ Trees ” for more information.
Because all types in C# are subtypes of object , which is a reference type, every value type is a subtype of at least one reference type (however, value types cannot themselves have subtypes). It is therefore possible to assign an instance of a value type to a variable of a reference type; for example:
When this is done, a boxed version of the value type is constructed, and the value copied to it. The boxed version of the value type is just like the original value type, except that it is allocated from the heap and accessed by reference, not by value. A reference to this boxed version is then assigned to the variable of the reference type. Note that multiple variables of the reference type may refer to the same boxed instance of the value type. Note that boxing may also occur when passing parameters. For example, suppose we have a method:
If we call F with a parameter of 3, then 3 will need to be copied to a boxed int , and a reference to this boxed int will be assigned to x within F .

C# Value Type and Reference Type with Examples
In c#, we have two ways to allocate the space in memory, i.e., either on stack or heap memory based on the Value Type or Reference Type parameters.
In the previous chapter, we learned about Data Types in C# and how the Data Types in c# are categorized as a Value Type or Reference Type with examples.
We will now learn the value types and reference types in c# and how the Value Type and Reference Type parameters will hold the data and memory in the same location with examples.
C# Value Types
In c#, a data type is a Value Type if it holds the value of the variable directly on its own memory space, and Value Types will use Stack memory to store the values of the variables.
For example, if we define and assign a value to the variable like int x = 123; then the system will use the same memory space of variable ‘ x ’ to store the value ‘ 123 ’.
Following is the pictorial representation of value types in the c# programming language.

The following are the different data types that will fall under Value Type in c# programming language.
C# Pass Value Type by Value
In c#, if we pass a value type variable from one method to another method, the system will create a separate copy for the variable in another method. If we make changes to the variable in one method, it won’t affect the variable in another method.
Following is the example of passing the value type by value in c# programming language.
If you observe the above example, we defined two variables ( num1 , num2 ) in the Main() method, and we are making changes to those variables by passing them to the Square() method, but those changes won’t affect the variables in Main() method.
When we execute the above program, we will get the result as shown below.
If you observe the above result, the changes made to variables in the Square() method didn’t affect the variables in the Main() method.
C# Reference types
In c#, Reference Types will contain a pointer that points to another memory location that holds the data. The Reference Types won’t store the variable value directly in its memory. Instead, it will store the memory address of the variable value to indicate where the value is being stored.
For example, if we define and assign a value to the variable like string name = "Suresh Dasari" ; then the system will store the variable value “ Suresh Dasari ” in one location and the variable " name " in another location along with the memory address of the variable value.
Following is the pictorial representation of reference type in c# programming language.

The following are the different data types that will fall under Reference Type in c# programming language.
- All Arrays , Even if their elements are value types
Pass Reference Type by Value
In c#, if we pass a reference type variable from one method to another method, the system won’t create a separate copy for that variable. Instead, it passes the address of the variable, so if we make any changes to the variable in one method, that also reflects in another method.
Following is the example of passing the reference type by value in the c# programming language.
If you observe the above example, we created a new class called “ Person ” and created an instance of a new class ( Person ) and assigned values to the variables in Main() method, and we are making changes to those variable by passing it to Square() method and those changes will be reflected in Main() method.
When you execute the above program, you will get the result as shown below.
If you observe the above result, the changes we made to variables in the Square() method also reflected for the variables in the Main() method.
This is how we can use Value Type and Reference Type in c# programming language based on our requirements.
Table of Contents
- Values Types and Reference Types in C# with Examples
- Value Types in C# with Example
- C# Pass Value Type By Value Example
- Reference Types in C# with Examples
- C# Pass Referece Type By Value Example
Value and Reference Types 2020

Unlike array, strings, or enumerations, C# structures do not have an identically named representation in the .NET library.
In other words, there is no such thing as System.Structure class. But structures are implicitly derived from System.ValueType . That is, the role of System.ValueType is to ensure that the derived type is allocated on the stack rather than the garbage collected heap .
The only purpose of System.ValueType is to override the virtual methods defined by System.Object to use value-based vs. reference-based, semantics. The base class of ValueType is System.Object . Actually, the instance methods defined by System.ValueType are identical to those of System.Object :
The fact that value types are using value-based semantics, the lifetime of a structure (which includes all numerical data types as well as any enum or custom structure) is very predictable. When a structure variable falls out of the defining scope, it is removed from memory immediately:
When we assign one value type to another, a member-by-member copy of the field data is achieved. In the case of a simple data type such as System.Int32 . the only member to copy is the numerical value. However, in the case of our Point , the X and Y values are copied into the new structure variable. Let's look at the following example.
We created a variable of type Point and named p1 . Then it is assigned to another Point(p2) . Because Point is a value type, we have two copies of the Point type on the stack, each of which can be independently manipulated. So, when we change the value of p1.X , the value of p2.X is unaffected.
In stark contrast to value types, when we apply the assignment operator to reference types (meaning all class instances ), we are redirecting what the reference variable points to in memory. Let's look at the following example.
Output from the run is:
We used our PointRef type within the new method, RefTypeAssign() method. In the example, we have two references pointing to the same object on the managed heap. So, when we change the value of X using the p1 reference, p2.X reports the same value.
Assume we have the following reference (class) type that maintains an informational string that can be set using a custom constructor:
We want to contain a variable of this class type ( ShapeInfo ) within a value type named Rectangle . To allow the caller to set the value of the inner ShapeInfo member variable, we also provide a custom constructor, Rectangle() :
At this point, we have contained a reference type ( SahpeInfo ) within a value type ( Rectangle ). What happens if we assign one Rectangle variable to another? Given what we already know about value types, we would be correct in assuming that the integer data (which is a structure) should be an independent entity for each Rectangle variable. But what about the internal reference type ? Will the object's state be fully copied, or will the reference to that object be copied? To answer this question, let's define the following method and invoke it from Main() .
As we can see, when we change the value of the informational string using the r2 reference, r1 reference displays the same value. By default, when a value type contains other reference types, assignment results in a copy of the references. In this way, we have two independent structures, each of which contains a reference pointing to the same object in memory (shallow copy). When we want to perform a deep copy , where the state of internal references is fully copied into a new object, one approach is to implement the ICloneable interface.
Reference types or value types can obviously be passed as parameters to type members. However, passing a reference type (a class) by reference is quite different from passing it by value. To understand the distinction, let's take a look at the following Person class:
What's going to happen if we create a method that allows the caller to send in the Person type by value?
Note that PersonByValue() method attempts to reassign the incoming Person reference (p) to a new object as well as change some state data (Age). Now, combine all the routines we wrote and test:
The output we get:
The value of Age has been changed. Given that we could change the state of the incoming Person , what was copied? A copy of the reference to the caller's object. So, as the PersonByValue method is pointing to the same object as the caller, it is possible to alter the object's state data. What is not possible is to reassign what the reference is pointing to.
Let's make a new method which passes a reference type by reference using ref modifier.
Let's combine the routines and check to see what's the difference compared to the previous example:
Output we get this time:
As we see, an object named b returns after the call as a type named Mozart , as the method was able to change what the incoming reference pointed to in memory. The golden rule to keep in mind when passing reference types:
- If a reference type is passed by reference, the called may change the values of the object's state data as well as the object is referencing.
- If a reference type is passed by value, the called may change the values of the object's state data but not the object it is referencing.
Here is the summary of the core distinctions between value types and reference types.

Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization
Sponsor Open Source development activities and free contents for everyone.

IMAGES
VIDEO
COMMENTS
Hepatitis C, a virus that attacks the liver, is a tricky disease. Some people have it and may never know it as they are affected by any sorts of symptoms. It can remain silent until there is severe damage to your liver.
Whether in the form of a fizzy drink or flavored lozenges, cold and flu preventative supplements almost always highlight vitamin C as one of their key ingredients. So, what’s so magical about vitamin C? Also known as ascorbic acid, vitamin ...
A type “C” light bulb is a cone-shaped light bulb that is designed for small appliances and indicator lamps. The “C” refers to the cone shape of the bulb. There are many different kinds of “C” light bulbs. However, they generally fall into ...
There are four types that fall to the reference type category: String. Arrays. Class. Delegate.
C# Reference type assignment VS value type assignment · 2. The output is as it should be. · As per the example, it is only the 3rd point where it
Variables of reference types store references to their data (objects), while variables of value types directly contain their data. With
A value type variable cannot be null because it holds value, not a memory address. C# 2.0 introduced nullable types, using which you can assign null to a value
Reference types store a reference, that points to the data, which lives somewhere else in the machine's memory. When you assign the value of a
In particular, C# provides two types—class and struct, which are almost the same except that one is a reference type while the other is a value type. This
Value types are generally (not always) stored on the stack and are passed by copying. The way in which a variable assignment works differs
For reference types, the values are not stored directly into the space allocated for the variable. Instead, the variable stores a reference, which is like an
In c#, Reference Types will contain a pointer that points to another memory location that holds the data. The Reference Types won't store the variable value
This video will give you complete training in Value Types Vs Reference Types in C#How the assignment of ValueType and RefenceType works:Many
By default, when a value type contains other reference types, assignment results in a copy of the references. In this way, we have two independent structures