Skip to content

Instantly share code, notes, and snippets.

@omansak
Last active September 4, 2019 09:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save omansak/49b7e6442b6a32959a2f0736639993f7 to your computer and use it in GitHub Desktop.
Save omansak/49b7e6442b6a32959a2f0736639993f7 to your computer and use it in GitHub Desktop.
C# Value Type and Reference Type | In C#, these data types are categorized based on how they store their value in the memory (string vs StringBuilder || struct vs class)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
public class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
sb.Append("-1");
Foo foo = new Foo
{
StringBuilderValue = sb,
Int32Value = new Int32(),
IntValue = -1,
StringValue = new String("-1"),
String2Value = "-1"
};
foo.Int32Value = -1;
Foo.MyStruct ms = new Foo.MyStruct
{
StringValue = "-1",
IntValue = -1
};
Foo.MyClass mc = new Foo.MyClass
{
StringValue = "-1",
IntValue = -1
};
Console.WriteLine("\n\n### BEFORE ###\n\n");
Console.WriteLine("\n--- VARIABLE ---\n");
Console.WriteLine($"(Reference Class){nameof(foo.StringBuilderValue)}:{foo.StringBuilderValue}");
Console.WriteLine($"(Value string){nameof(foo.StringValue)}:{foo.StringValue}");
Console.WriteLine($"(Value String){nameof(foo.String2Value)}:{foo.String2Value}");
Console.WriteLine($"(Value int){nameof(foo.IntValue)}:{foo.IntValue}");
Console.WriteLine($"(Value Int32){nameof(foo.Int32Value)}:{foo.Int32Value}");
Console.WriteLine("\n--- STRUCT (Value) ---\n");
Console.WriteLine($"{nameof(ms.StringValue)}:{ms.StringValue}");
Console.WriteLine($"{nameof(ms.IntValue)}:{ms.IntValue}");
Console.WriteLine("\n--- CLASS (Reference) ---\n");
Console.WriteLine($"{nameof(mc.StringValue)}:{mc.StringValue}");
Console.WriteLine($"{nameof(mc.IntValue)}:{mc.IntValue}");
// Change values in another function
foo.ChangeValues(foo.StringBuilderValue, foo.StringValue, foo.String2Value, foo.IntValue, foo.Int32Value, ms, mc);
Console.WriteLine("\n\n### AFTER ###\n\n");
Console.WriteLine("\n--- VARIABLE ---\n");
Console.WriteLine($"(Reference Class){nameof(foo.StringBuilderValue)}:{foo.StringBuilderValue}");
Console.WriteLine($"(Value string){nameof(foo.StringValue)}:{foo.StringValue}");
Console.WriteLine($"(Value String){nameof(foo.String2Value)}:{foo.String2Value}");
Console.WriteLine($"(Value int){nameof(foo.IntValue)}:{foo.IntValue}");
Console.WriteLine($"(Value Int32){nameof(foo.Int32Value)}:{foo.Int32Value}");
Console.WriteLine("\n--- STRUCT (Value) ---\n");
Console.WriteLine($"{nameof(ms.StringValue)}:{ms.StringValue}");
Console.WriteLine($"{nameof(ms.IntValue)}:{ms.IntValue}");
Console.WriteLine("\n--- CLASS (Reference) ---\n");
Console.WriteLine($"{nameof(mc.StringValue)}:{mc.StringValue}");
Console.WriteLine($"{nameof(mc.IntValue)}:{mc.IntValue}");
Console.ReadLine();
/* OUTPUT
### BEFORE ###
--- VARIABLE ---
(Reference Class)StringBuilderValue:-1
(Value string)StringValue:-1
(Value String)String2Value:-1
(Value int)IntValue:-1
(Value Int32)Int32Value:-1
--- STRUCT (Value) ---
StringValue:-1
IntValue:-1
--- CLASS (Reference) ---
StringValue:-1
IntValue:-1
### AFTER ###
--- VARIABLE ---
(Reference Class)StringBuilderValue:1
(Value string)StringValue:-1
(Value String)String2Value:-1
(Value int)IntValue:-1
(Value Int32)Int32Value:-1
--- STRUCT (Value) ---
StringValue:-1
IntValue:-1
--- CLASS (Reference) ---
StringValue:1
IntValue:1
*/
}
public class Foo
{
public void ChangeValues(StringBuilder sb, String s, string s2, int i, Int32 i32, MyStruct ms, MyClass mc)
{
sb.Clear().Append("1");
s = "1";
i = 1;
i32 = 1;
s2 = "1";
ms.IntValue = 1;
ms.StringValue = "1";
mc.IntValue = 1;
mc.StringValue = "1";
}
public StringBuilder StringBuilderValue { get; set; }
public String StringValue { get; set; } // String = string
public string String2Value { get; set; }
public int IntValue { get; set; }
public Int32 Int32Value { get; set; }
public struct MyStruct
{
public string StringValue { get; set; }
public int IntValue { get; set; }
}
public class MyClass
{
public string StringValue { get; set; }
public int IntValue { get; set; }
}
}
}
@omansak
Copy link
Author

omansak commented Sep 4, 2019

Value Type
Structs and Enumeration falls under the Value type category. Structs are the numeric types(int, char, byte, float, double), bool and even user defined structs.
So, “What’s actually a value type variable?”. Well, they are variables that store the actual data, rather than a reference to it.
They are passed by value; meaning if you assigned a variable to another one, it gets assigned to a new, independent copy of the variable’s value, and any change in either variable will affect only the changed variable. Also it’s worth to mention that Value types are allocated on the stack.

@omansak
Copy link
Author

omansak commented Sep 4, 2019

Reference Type
Class, interface, string, object, All of them fall under Reference type category. So, the question again “What’s actually a reference type variable?”. Not surprisingly, Those are the Variables that store references to the actual data rather than the data itself. Reference types are allocated on the heap.
Now, if you are following along from the previous section, you might be asking these questions:
“Are they passed by reference or value?”. Assigning a Reference type variable to another variable actually copies the reference to the object but not the object itself. It means, since the reference type variable holds the reference to the actual data, so it passes this reference and not the actual data. So, it’s pass by value!
“What if i assigned a reference type variable to anther, and then i changed any of them?”. Since they are referencing the same memory location, so any changes in any of the variables will affect the same memory location, and hence, both reference type variables will get affected by this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment