AlgoMaster Logo

Variables & Data Types

Last Updated: May 17, 2026

9 min read

Variables are the names you attach to pieces of data so your program can read and update them by name instead of juggling raw values. C# adds two ideas on top of that: every variable has a fixed type the compiler enforces, and the language ships with a small, well-defined set of built-in types you'll see everywhere. This lesson introduces both, gives you a feel for the type system at a high level, and gets you comfortable declaring variables before later lessons go deep on each category.

What a Variable Is

A variable is a labeled slot in memory. You give it a name, you tell C# what kind of value it holds, and you assign a value to it. From that point on, the name refers to the value.

Three variables, three different types, one print line. The shape of every declaration is the same:

The type tells C# what kind of value the variable can hold. The name is the identifier you'll use to refer to it. The = is the assignment operator, and the value on its right is what gets stored. The semicolon ends the statement.

Once a variable exists, you can reassign its value as long as the new value is the same type:

What you can't do is store a value of a different type:

The compiler stops you before the program runs, with the error CS0029: Cannot implicitly convert type 'string' to 'int'. That's the whole point of C#'s type system, and it's the next idea worth pinning down.

Type Safety in C\#

C# is statically typed: every variable has a type fixed at compile time. C# is also strongly typed: the compiler doesn't let you mix types silently. If you declare a variable as int, you can't quietly slip a string into it and hope it works.

The benefit shows up before your program ever runs. Type errors are caught by the compiler, not by your users:

The compiler rejects this with CS0019: Operator '+' cannot be applied to operands of type 'int' and 'string'. You haven't built anything, run anything, or shipped anything yet. The mistake is caught at the moment you save the file.

This is different from dynamically typed languages, where the same expression might run for months and only blow up when an unusual code path hits it. In C#, that whole category of bug is gone by design.

The C# Type System at a Glance

Every type in C# falls into one of two big families: value types and reference types. The split shows up in how the value is stored and how it behaves when you assign or pass it around. We'll go deep on each family in the next two chapters, but here's the preview you need now.

A value type holds its data directly. When you assign a value type to another variable, the data is copied. The two variables hold independent values from that point on. int, double, bool, char, and decimal are all value types. The _Value Types_ lesson covers these in depth.

A reference type holds a reference to data stored elsewhere in memory. When you assign a reference type to another variable, only the reference is copied. Both variables now point at the same underlying data. string, arrays, and any class you define are reference types. The _Reference Types_ lesson covers these in depth.

The diagram groups every C# type into one of these two families and lists a few examples in each. The exact storage rules (stack versus heap, copy versus reference) belong to the _Value Types_ and _Reference Types_ lessons. For now, hold on to the high-level idea: value types are copied, reference types are shared.

Built-in Types You'll See Everywhere

C# ships with a small set of built-in types covering the common cases: whole numbers, fractional numbers, money, true/false, single characters, and text. You'll meet each one in detail later. The table below gives you a quick overview so the rest of the chapter has names to refer to.

CategoryKeywordHoldsExample value
IntegerintWhole number (32-bit)42
IntegerlongLarger whole number (64-bit)9_000_000_000L
IntegershortSmaller whole number (16-bit)(short)100
IntegerbyteWhole number 0 to 255(byte)200
Floating-pointfloat32-bit fractional number3.14f
Floating-pointdouble64-bit fractional number3.14159
DecimaldecimalHigh-precision number for money49.99m
Booleanbooltrue or falsetrue
CharactercharA single character'A'
TextstringA sequence of characters"hello"

The keyword on the left is the one you actually type in your code. int is the default choice for whole numbers, double for fractional ones, decimal when money is involved, and string for any text. The other types exist for specific cases (a byte for a single octet, a short when memory is tight) and you'll reach for them less often.

A short example using one of each:

Notice that bool prints as True (capitalized) when interpolated. That's the standard string form of true and false in C#.

Literals: How You Write Values in Source Code

A literal is a fixed value written directly in the code, like 42, "hello", or true. C# has rules for how each kind of literal is recognized, and a few of them have suffixes that change the literal's type.

Integer literals are written without quotes or a decimal point. By default they're int. Append L for a long:

You can use underscores anywhere inside a numeric literal to make it readable. 1_000_000 and 1000000 are the same value.

Floating-point literals include a decimal point. By default they're double. Append f for a float:

Decimal literals require the m suffix. Without it, 19.99 is a double, and assigning a double to a decimal fails to compile:

The m is short for "money" and is the one suffix you'll forget the most when starting out. The compiler error CS0664 is your reminder.

Character literals use single quotes and hold exactly one character:

The \n is an escape sequence that represents a newline character. Other common escapes are \t (tab), \\ (a backslash), and \' (a single quote inside a character literal).

String literals use double quotes:

Backslashes inside a regular string have to be escaped, which is why the path example uses \\ for a single backslash. There's a cleaner form called a verbatim string (@"C:\Users\Alice") that you'll see later.

Boolean literals are the two keywords true and false:

Declaration, Initialization, and Default Values

There's a difference between declaring a variable (telling the compiler it exists and what type it is) and initializing it (giving it its first value). Most of the time you do both on the same line:

You can also split them:

C# is strict about one thing: a local variable must be assigned before you read it. This compiles fine, but the next snippet doesn't:

The compiler reports CS0165: Use of unassigned local variable 'quantity'. The rule prevents a whole class of bugs where a variable accidentally gets read before it's been given a value.

Class fields (variables that live inside a class, not a method) play by different rules. They get a default value automatically:

  • Numeric types default to 0 (or 0.0).
  • bool defaults to false.
  • char defaults to '\0' (the null character).
  • Reference types default to null.

You can also ask explicitly for a type's default using the default keyword:

The ? on string? marks the variable as nullable so it can hold null. The _Nullable Types_ lesson covers these properly.

Variable Scope

A variable's scope is the region of code where it exists and can be used. The basic rule in C# is block scope: a variable declared inside a pair of braces { } is only visible inside those braces.

discount lives inside the if block. Outside of it, the name doesn't exist. outerTotal, declared in the surrounding scope, is visible inside the if block and after it.

The same rule applies to loop variables, method parameters, and any other declaration. The general idea: a variable is alive from the line it's declared until the closing brace of the block that contains it.

You can't declare two variables with the same name in the same scope, and you can't shadow an outer scope's variable with a new declaration of the same name in C#:

The compiler stops this so you can't accidentally write code that reads from the wrong items depending on context.

Naming a Variable

Variable names follow a few simple rules. They must start with a letter or underscore, can contain letters, digits, and underscores after that, and they can't be C# keywords like int or class. They're case-sensitive: total and Total are different names.

Beyond the rules, there's a strong convention: local variables and method parameters use camelCase, where the first word is lowercase and each later word starts with a capital letter.

That's customerName, not customername, CustomerName, or customer_name. C# has full naming conventions for when to use PascalCase, when underscores show up, and how to handle abbreviations.

The other half of naming well is choosing meaningful words. x, temp, and data describe nothing. cartTotal, customerEmail, and discountPercent tell the next reader (often future-you) exactly what's in the variable.

Constants: A Preview

Sometimes you want a name for a value that should never change while the program runs. C# has a const keyword for that:

A const must be initialized when it's declared, and trying to assign to it later is a compile error:

const is for values known at compile time, like the tax rate above, the maximum number of items in a cart, or a fixed conversion factor. There's a related keyword (readonly) for values fixed at run time but not at compile time. The _const & readonly_ lesson covers both properly.

Putting It Together

A small program that pulls every idea in this chapter into one place:

Five variable types appear here: string for names, int for quantity, decimal for money, bool for membership, and a const decimal for the tax rate. Every variable is declared with a type and a value, and every name describes what it holds.

Summary

  • A variable is a named slot for data. The declaration shape is type name = value;, with the type fixed at compile time.
  • C# is statically and strongly typed. The compiler enforces types and rejects invalid assignments before the program runs.
  • Every C# type falls into one of two families: value types (copied on assignment) or reference types (shared by reference). The _Value Types_ and _Reference Types_ lessons cover each in depth.
  • The built-in types you'll use most are int for whole numbers, double for general fractional numbers, decimal for money, bool for true/false, char for a single character, and string for text.
  • Literals have suffixes that change their type: m for decimal, f for float, L for long. Without a suffix, decimal-point numbers are double and whole numbers are int.
  • Local variables must be assigned before they're read. Class fields get a default value automatically (0 for numbers, false for bool, null for reference types).
  • Variables have block scope: they exist from their declaration until the closing brace of the block that contains them.
  • const names a value fixed at compile time, so the compiler refuses any later reassignment.