Codectionary / Developer documentation / C#

Variables & Data Types

C# is a statically-typed language, meaning every variable's type is fixed at compile time. Built-in value types include int, double, decimal, bool, and char, while string and object are reference types. The var keyword lets the compiler infer a variable's type from its initializer, but the variable is still strongly typed underneath - it just saves you from writing the type name explicitly.

About C#

C# is a statically typed, general-purpose language in the .NET ecosystem. It combines object-oriented features with modern tools for building web services, desktop applications and games.

  • .NET web APIs
  • Desktop applications
  • Unity games
Created by
Anders Hejlsberg and the Microsoft team
First released
2002 · version 1.0 (announced in 2000)
Version / standard
C# 14

Current stable language release. Availability depends on your .NET SDK.

In the real world

Facts checked 8 September 2026. Links open the sources; examples describe specific products or documented uses.

Syntax

type variableName = value;

Examples

A small working example

Follow the values through this example, then change one input.

using System;
class Program {
    static void Main() {
        int lessons = 3;
        string language = "C#";
        Console.WriteLine($"{language}: {lessons} lessons");
    }
}

Declaring Variables

Creating variables of common built-in types.

int age = 21;
double gpa = 3.8;
decimal price = 19.99m;   // m suffix for decimal - ideal for money
char grade = 'A';
bool isStudent = true;
string name = "Fola";

Console.WriteLine($"{name}, {age}, {gpa}, {grade}, {isStudent}");

Implicit Typing with var

The compiler infers the type from the right-hand side - the variable is still strongly typed, just without an explicit type name.

var count = 10;         // inferred as int
var total = 19.99;      // inferred as double
var label = "Total: ";  // inferred as string

// count = "text";  // Error! count is still an int under the hood
Console.WriteLine(label + total);

Constants with const and readonly

const values are fixed at compile time; readonly values can be set once, at declaration or in a constructor.

const double Pi = 3.14159;         // must be assigned a compile-time constant
Console.WriteLine(Pi);

class Circle
{
    public readonly double Radius;  // can be set in the constructor, not after

    public Circle(double radius)
    {
        Radius = radius;
    }
}

Nullable Value Types

Value types like int normally can't be null - appending ? makes them nullable.

int? age = null;          // nullable int
double? score = 85.5;

if (age.HasValue)
{
    Console.WriteLine(age.Value);
}
else
{
    Console.WriteLine("Age not set");
}

int actualAge = age ?? 0;  // null-coalescing: use 0 if age is null
Console.WriteLine(actualAge);

Best practices

  • Use PascalCase for public members and camelCase for local variables and private fields, following standard C# naming conventions
  • Use var when the type is obvious from the right-hand side (var list = new List<string>();), but prefer an explicit type when it improves readability
  • Use decimal, never double or float, for money and other values where exact precision matters - double introduces small rounding errors
  • Use nullable value types (int?) and the null-coalescing operator (??) to handle "no value" cases explicitly, rather than relying on magic sentinel numbers

At a glance

Purpose
Applications on the .NET platform
File extension
.cs
Runs in
.NET runtime
Usually used with
.NET SDK and libraries

In plain English

A C# local variable has a type that controls which values it can hold. var asks the compiler to infer that type from its initial value.

What you’ll learn

  • Declare a typed local.
  • Use type inference.
  • Choose a suitable numeric type.

Breaking down the syntax

int
An integer type.
string
A text reference type.
var
Infers a local variable type from its initializer.

How it works

Declare

Choose a name and type, or infer it.

Assign

Supply a compatible value.

Use

Operations are checked against that type.

When should I use this?

Name intermediate results and application state with types that communicate their meaning.

Common mistakes

A common trap

var inferred int; it does not make the variable dynamically typed.

Incorrect

var count = 1;
count = "two";

Corrected

var count = 1;
count = 2;

Compare approaches

  • Explicit type: Make the type visible at the declaration.
  • var: Use inference when the initializer makes the type clear.

Explore deeper

decimal literals

Use the m suffix for decimal literals, for example 12.50m. Decimal arithmetic is often useful for base-10 financial values; rounding rules still need an explicit application policy.

Specifications & further reading

Related C# documentation

Console.WriteLine / ReadLine
The Console class, from the System namespace, provides the standard way to read from and write to the terminal in a C# console application. Console.WriteLine() prints a value followed by a newline, Console.Write() prints without one, and Console.ReadLine() reads a full line of text typed by the user, always returning it as a string.
Comments & XML Documentation
C# supports single-line comments with //, multi-line comments with /* */, and a special triple-slash XML documentation format (///) placed above a member. XML doc comments support tags like <summary>, <param>, and <returns>, and are used by Visual Studio and other IDEs to power IntelliSense tooltips and can be compiled into full API documentation.
Arithmetic & Assignment Operators
C# provides the standard arithmetic operators for numeric computation: +, -, *, / for division, and % for the remainder. Integer division truncates any decimal part, just as in many C-family languages. Compound assignment operators (+=, -=, etc.) combine an operation with assignment, and increment/decrement operators (++, --) come in prefix and postfix forms that differ subtly in when the value updates relative to being used.
Comparison & Logical Operators
Comparison operators (==, !=, <, >, <=, >=) compare two values and produce a bool. Logical operators (&&, ||, !) combine or invert boolean expressions, with && and || short-circuiting so the second operand is skipped once the result is already determined. For strings, == compares content by default (unlike some languages), since string overrides the equality operator.