C# (.NET 8 LTS) track

Lesson 02 · Part 1: Basics

Variables and Types

Declare variables and work confidently with C# value types, reference types and type inference.

Part 1: Basics5 min readFree lesson

Programming is ultimately “memorizing and processing values.” C# is a statically typed language, so all variables are typed at compile time. In this section, we discuss the differences between the basic type and the value/reference type.

Learning Objectives

  • Know the size and range of basic types int/long/double/decimal/bool/char/string
  • Understand the difference between value type and reference type
  • Use var / const / readonly where appropriate.
  • Understand the immutability of strings
  • Know what boxing is and why it is slow

Key concepts

1) Built-in types

Type size Scope/Use Yes
int 4 B Approximately ±2.1 billion, general integer int n = 100;
long 8 B Approximately ±9.2×10¹⁸, large integer long big = 10_000_000_000L;
double 8 B floating point, common real number double pi = 3.14;
decimal 16 B 28-digit precision real number, for money calculations decimal won = 1500m;
bool 1 B true / false bool ok = true;
char 2 B Unicode single character char c = 'A';
string variable string (reference type) string s = "hi";

For long, add L at the end, and for decimal, add m at the end.

2) Value type vs reference type

  • Value type (struct, int, double, bool, char, enum...): The value itself is stored in a variable. Duplicate entire copy when copying.
  • Reference type (class, string, array...): There is an object on the heap and the variable only has its address. Only share the address when copying.
int a = 10;
int b = a;      //Copy value
b = 20;
//a == 10, b == 20 (independent of each other)

int[] arr1 = [1, 2, 3];
int[] arr2 = arr1;   //Copy reference
arr2[0] = 99;
//arr1[0] == 99 (points to the same array)

3) var: Type inference

In var, the compiler infers the type by looking at the right side. Types do not disappear, they are just omitted.

var name = "Alice";   // string
var age = 30;         // int
var pi = 3.14;        // double

It can only be used in local variables, and cannot be used without initialization (var x; is not possible).

4) const and readonly

  • const: compile time constant. Initialized upon declaration and cannot be changed afterwards. Available only for basic type and string.
  • readonly: Can only be assigned once at runtime. Used for the value determined in the constructor.
const double Pi = 3.14159;        //A value that never changes
//Pi = 3.14;  // compile error

5) Strings are immutable

string is a reference type, but its contents cannot be changed. += or Replace creates and returns a new string.

string s = "Hello";
s += ", World!";   //Creates a new string, s points to a new object

6) Boxing

When a value type is treated as a reference type such as object, it is the operation of creating a copy on the heap. Avoid it as much as possible as it is slow and puts pressure on the GC.

int n = 42;
object o = n;     //Boxing: Creating a new object on the heap
int m = (int)o;   //Unboxing

See as example

Example 1 — Primitives/Program.cs: Examining the basic types

int i = 100;
long l = 10_000_000_000L;
double d = 3.14;
decimal m = 1500.99m;
bool b = true;
char c = 'A';
string s = "hello";

Console.WriteLine($"int    : {i} ({sizeof(int)} B)");
Console.WriteLine($"long   : {l} ({sizeof(long)} B)");
Console.WriteLine($"double : {d} ({sizeof(double)} B)");
Console.WriteLine($"decimal: {m}");
Console.WriteLine($"bool   : {b}, char: {c}, string: {s}");

Execution result

int    : 100 (4 B)
long   : 10000000000 (8 B)
double : 3.14 (8 B)
decimal: 1500.99
bool: True, char: go, string: hello

Memo: sizeof(decimal) is omitted because it requires an unsafe context. You can distinguish between digits as _ (10_000_000_000).

Example 2 — ValueVsReference/Program.cs: Comparing copy behavior

namespace CodingNow.Lecture.Basics02;

internal static class Program
{
    public static void Main()
    {
        Point p1 = new(1, 2);
        Point p2 = p1;          //Copy value
        p2.X = 99;
        Console.WriteLine($"p1=({p1.X},{p1.Y})  p2=({p2.X},{p2.Y})");

        Box b1 = new() { Value = 10 };
        Box b2 = b1;            //Copy reference
        b2.Value = 99;
        Console.WriteLine($"b1={b1.Value}  b2={b2.Value}");
    }
}

internal struct Point
{
    public int X;
    public int Y;
    public Point(int x, int y) { X = x; Y = y; }
}

internal class Box
{
    public int Value;
}

Execution result

p1=(1,2)  p2=(99,2)
b1=99  b2=99

Memo: struct is a value type, so it is independent, and class is a reference type, so they share the same object.

Example 3 — VarConst/Program.cs : var, const, readonly

var name = "Alice";   //Inference: string
var age = 30;         //Inference: int

const double Pi = 3.14159;
const string Greet = "Hello!";

Console.WriteLine($"{name}, {age} years old, {Greet} (Pi={Pi})");
//Pi = 3.0;   // compile error

Execution result

Alice, 30 years old, Hi! (Pi=3.14159)

Note: var is used for readability, but if the right-hand side type is not clear, an explicit type is better.

Example 4 — StringBasics/Program.cs: String immutability

string a = "Hello";
string b = a;
a += ", World!";          //Create a new string

Console.WriteLine($"a = {a}");
Console.WriteLine($"b = {b}");   //b is still "Hello"

//Comparison of connection methods
string c1 = string.Concat("Value:", 42);
string c2 = $"value:{42}";          //String interpolation (recommended)
Console.WriteLine(c1);
Console.WriteLine(c2);

Execution result

a = Hello, World!
b = Hello
Value:42
Value:42

Note: Even after a += "...", b still points to the original string. Strings are immutable, so they are safe to share.

Common Mistakes

  1. Overflow by using int to exceed the int range (about ±2.1 billion) — the larger number is long.
  2. Use double for money calculations — floating point error. Must be decimal.
  3. Using var without initialization like var x; — compilation error.
  4. Accumulate string into += in a loop — new object each time. When there are many, it is StringBuilder (refer to Part 16).
  5. Confusion between const and readonly — const is a compile-time constant, and readonly is a one-time assignment at runtime.

Cleanup

  • Integers are int/long, real numbers are double (science) / decimal (money)
  • Value types are copied in their entirety when copied, and reference types share only the address.
  • var is convenient for type inference, and const is absolutely immutable.
  • string is a reference type, but immutable — can be safely shared
  • Boxing may occur if you enter a value type as object → Avoid it as much as possible.

Try it yourself

cd src/Primitives && dotnet run
cd ../ValueVsReference && dotnet run
cd ../VarConst && dotnet run
cd ../StringBasics && dotnet run

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/Primitives/Primitives.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/Primitives/Program.csC#
//Basic types and sizes
int i = 100;
long l = 10_000_000_000L;
double d = 3.14;
decimal m = 1500.99m;
bool b = true;
char c = 'A';
string s = "hello";

Console.WriteLine($"int    : {i} ({sizeof(int)} B)");
Console.WriteLine($"long   : {l} ({sizeof(long)} B)");
Console.WriteLine($"double : {d} ({sizeof(double)} B)");
Console.WriteLine($"decimal: {m}");
Console.WriteLine($"bool   : {b}, char: {c}, string: {s}");
src/StringBasics/Program.csC#
//Strings are immutable
string a = "Hello";
string b = a;
a += ", World!";          //only a points to a new object

Console.WriteLine($"a = {a}");
Console.WriteLine($"b = {b}");

//Comparison of connection methods
string c1 = string.Concat("Value:", 42);
string c2 = $"value:{42}";   //String interpolation (recommended)
Console.WriteLine(c1);
Console.WriteLine(c2);
src/StringBasics/StringBasics.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/ValueVsReference/Program.csC#
namespace CodingNow.Lecture.Basics02;

internal static class Program
{
    public static void Main()
    {
        //Value type (struct): Copy the entire value
        Point p1 = new(1, 2);
        Point p2 = p1;
        p2.X = 99;
        Console.WriteLine($"p1=({p1.X},{p1.Y})  p2=({p2.X},{p2.Y})");

        //Reference type (class): Shares address
        Box b1 = new() { Value = 10 };
        Box b2 = b1;
        b2.Value = 99;
        Console.WriteLine($"b1={b1.Value}  b2={b2.Value}");
    }
}

internal struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

internal class Box
{
    public int Value;
}
src/ValueVsReference/ValueVsReference.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
src/VarConst/Program.csC#
//var: Compiler looks at the right side and infers the type
var name = "Alice";   // string
var age = 30;         // int

//const: compile-time constant (cannot be changed later)
const double Pi = 3.14159;
const string Greet = "Hello!";

Console.WriteLine($"{name}, {age} years old, {Greet} (Pi={Pi})");
//Pi = 3.0;   // compile error
src/VarConst/VarConst.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Assignment

Problem 1 — Profile Card

  • Reference solution: shown below
  • Key concepts: declaring variables, choosing appropriate types, string interpolation

Requirements

  • Put the following information in a variable of the appropriate type.
  • Name (string)
  • Age (int)
  • Height in cm (double)
  • Whether you are a student (bool)
  • Print everything one line at a time

Expected output

=== Profile ===
Name: Jisoo
Age: 25
Height: 172.5cm
Student: True

Hint

  • For values with decimals like keys, use double
  • If you print the bool value as is, True / False appears.

Problem 2 — Four arithmetic operations on two integers

  • Reference solution: shown below
  • Key concepts: Console.ReadLine, int.Parse, arithmetic operators

Requirements

  • Two integers are input from the user.
  • Prints sum, difference, product, quotient, and remainder.

Expected output

First integer: 10
Second integer: 3
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 / 3 = 3
10 % 3 = 1

Hint

  • Convert to int a = int.Parse(Console.ReadLine()!); format
  • ! is an operator that tells the compiler that it is “not null” (see Section 3 for details)
  • / is only the portion between integers, and % is the remainder.

Check the correct answer

After solving it yourself, compare it with the reference solution below.

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

Homework01/Homework01.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
Homework01/Program.csC#
//profile card
string name = "exponent";
int age = 25;
double height = 172.5;
bool isStudent = true;

Console.WriteLine("=== Profile ===");
Console.WriteLine($"Name: {name}");
Console.WriteLine($"Age: {age}");
Console.WriteLine($"Height: {height}cm");
Console.WriteLine($"Student: {isStudent}");
Homework02/Homework02.csprojText
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics02</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
Homework02/Program.csC#
//Four basic operations of two integers
Console.Write("First integer:");
int a = int.Parse(Console.ReadLine()!);

Console.Write("Second integer:");
int b = int.Parse(Console.ReadLine()!);

Console.WriteLine($"{a} + {b} = {a + b}");
Console.WriteLine($"{a} - {b} = {a - b}");
Console.WriteLine($"{a} * {b} = {a * b}");
Console.WriteLine($"{a} / {b} = {a / b}");
Console.WriteLine($"{a} % {b} = {a % b}");

Learn this lesson with a mentor

Work through the C# (.NET 8 LTS) track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now