13 min read

Variables

The Crash Course

What is a Variable?

In this tutorial, we’ll cover one of the most important fundamentals of programming: variables. Variables are how a C# program can store data. Any program that does anything real will use them.

In this tutorial, we’ll discuss how to make and use variables. We’ll also discuss the different types of variables that you can use.

Imagine you are making a game and want to keep track of a player’s score or the number of lives they have left.

A variable is like a little bucket to put stuff in. You can change what thing is currently in the bucket, but it can only hold one item at a time.

Each variable also has a name. The variable’s name will allow you to refer to it throughout your code.

In C#, each variable also has a type. Each piece of data has a specific type, and a variable can only store data if the type is right.

The reason for this is that each type stores its content in memory –the bits and bytes where your variable actually lives–in different ways. If data was stored in memory using one type’s scheme, and then accidentally tried to access it with another type’s scheme, bad things would happen.

(The good news is, there are mechanisms that will let us convert from one type to another when we need to.)

To summarize, each variable will have:

  1. A name.
  2. A type.
  3. The value that it is currently holding.

Creating Variables

Let’s talk about how to make a variable. This is simple to do, by adding a line like the following in your code:

int score;

This is called a variable declaration , or you could say that this line declares a variable. (“I hereby declare that there shall be a variable called score, and decree that it shall hold things of the type int!”)

The int part is the variable’s type–an integer. The score part is the variable’s name. And like most statements in C#, this one ends with a semicolon.

note

An integer is any number that doesn’t have a fractional or decimal part. 0, 1, 2, 3, 4, …, as well as -1, -2, -3, ….

There are lots of types to choose from in C#, and before long, we’ll be defining our own custom types as well. Sometimes, it is a challenge to know which of the many types to pick. That’s just another one of those things that takes some practice to get good at.

Variable names can be made up of any number or letter, or the underscore (_) character, though you cannot start a variable’s name with a number. So score, hamburger, _aPictureIsWorthA1000Words are all allowed names, but 1, taco-poptart, and 1stTry are not.

You want to pick a name that will help you remember what it is used for.

Assigning Values to Variables

With a variable declared, our next task is to put a value in the variable. This is done with the assignment operator , which is an = sign. On a line below the previous declaration, you could do the following, which puts the integer 0 into the variable score:

score = 0;

The = sign is a little different in C# than you might be used to in math. This is not about equality. score does not equal 0. This says, “Put the specific value of 0 into the variable called score”. If that is confusing, you could “read” the equals sign as “gets assigned” or simply “gets.” So you might read the line above as, “The variable score gets assigned a value of 0.”

That’s not the only value you can assign to score:

score = 4;
score = 11;
score = -1564;

While you only declare each variable once, you can assign values to a variable as often and whenever you want. (Though you must declare a variable before you can use it.)

Initializing a Variable

The first time you assign a value to a variable, it is called initializing the variable. You must initialize a variable before you can try to retrieve data from it, so you should always initialize your variables to good starting values.

Because you typically want to initialize a variable soon after declaring it, there is a way to do both in a single line:

int theMeaningOfLife = 42;

Reading Values from a Variable

Storing data is great, and all, but if we don’t ever use the data, there isn’t much point in storing it.

You can retrieve the value currently in a variable by simply using its name. To illustrate:

int number = 4;
Console.WriteLine(number);

Referencing a variable by name will always retrieve the current value out of the variable. Consider what output this code might have:

int number = 4;
Console.WriteLine(number);

number = 8;
Console.WriteLine(number);

number = 12;
Console.WriteLine(number);

This will display the following:

4
8
12

Expressions

With that last sample, you might be wondering why we’d even use variables. For example, why couldn’t we have simplified that last sample to simply this?

Console.WriteLine(4);
Console.WriteLine(8);
Console.WriteLine(12);

If that was truly all we were trying to accomplish, we definitely could have simplified it in that way.

But, of course, there is a lot more we can do with variables.

One key ingredient in C# programs is an expression . An expression is a little chunk of code that the computer can evaluate to compute a value. You’ve seen expressions before, in the math world. 2 + 2 is an expression, for example, and so is x - 1. While we’ll look at mathematical expressions in more detail in a future tutorial, you can start to imagine how you can build expressions that use variables to do some complex operations in your program.

In fact, for our next example, let’s introduce our second variable type: string. A string is just a fancy programmer word for text.

So you can declare the following variable that is designed to store text:

string name = "RB";

You can then use it in an expression like this:

Console.WriteLine("Hello, " + name);

That "Hello, " + name is an expression. It will combine two pieces of text together into a single, longer piece of text (string). The combination is what is given to WriteLine to display.

If we change the variable, we get different output.

In fact, fixed values–called literals –are also expressions. They’re the simplest flavor of expressions.

Naming a single variable, such as a plain old name, is an expression as well.

Meanwhile, an expression with a + is sort of a compound or composite expression, which lets you combine two smaller expressions together. So in the code "Hello, " + name, The literal string "Hello, " is an expression, the variable reference name is an expression, and the whole thing ("Hello, " + name) is an expression.

You can combine lots of things together into more and more complex expressions. For example:

Console.WriteLine("Hello, " + name + "! " + "How are you?");

Expressions can grow quite large. If they start to get too hard to understand quickly, you might want to break them up into smaller pieces instead, to make them easier to understand.

string name = "RB";
string greeting = "Hello, " + name + "!";
string theQuestion = "How are you?";
Console.WriteLine(greeting + " " + theQuestion);

Variable Types

Let’s take a moment and look at the basic types that are available in C#. Keep in mind that these are just the primitive types–the most foundational types. There are lots of other types that exist, and we’ll get to them later. (Even Console is a type!)

int, short, and long

The types int, short, and long store integers, but use different numbers of bytes and with different ranges.

Most C# programmers tend to default to int, unless they know it isn’t big enough, or there isn’t much memory, in which case, they might pick one of the other types.

You might be asking, “Why is the range of integers limited?”

Good question!

In short, the more bits or bytes you use, the more possible values you can represent. With just one bit (a single 0 or 1), you can represent only two possibilities. With two bits, you can represent four. Each bit you add doubles the number of possible options you can represent.

But unless you’re using a scheme to add more bits and bytes as needed as the number gets bigger, you will always have limits to how big you can make things.

note

Technically, there is a way you can grow to numbers that are arbitrarily large–as big as you need. Most things don’t need this capability, and a computer’s hardware–the circuitry itself–is just not designed to deal with such numbers. It is rarely needed, and much slower, and so it isn’t the typical approach in any programming language, including C#.

For all three of these, you can make a literal of these types in the exact same way you make a literal for the int type:

short a = 14;

When you run your program, if the number isn’t in the right range for the type you are trying to assign it to, your program won’t compile, and it will tell you that it is because the number isn’t in the range supported by the type.

uint, ushort, and ulong

The int, short, and long types are all signed types, meaning they have a positive or negative sign on them. Since these types must represent both positive and negative values, they must reserve half of the range for negative values.

There are situations where negative values just aren’t needed, and you’d prefer to use the extra range to count higher. That is where uint, ushort, and ulong come in. These are unsigned types. They can’t store negative values, but their maximum is twice as high as their signed counterparts:

Most C# programmers will typically prefer the signed types instead of these unsigned types, unless there’s a very strong reason for using these. So they don’t see nearly as much use.

Literal values for these three types is also done like an int, and the compiler will check its range for you (including stopping you from accidentally using a negative value):

ulong bigNumber = 10000000000000;

byte and sbyte

There is also a type that represents just a single byte: the byte type. The byte type can represent numbers in the range 0 to 255. In that sense, you could think of it as an unsigned, very tiny integer type. But in practice, it is more often used in big collections to represent arbitrary piles of binary data.

It has a signed counterpart: sbyte, which can store numbers from -127 to +128, though sbyte is not used very often.

Making a literal of the byte and sbyte types works the same as int:

byte b = 10;

float, double, and decimal

Let’s broaden our perspective to go beyond just integers. The so-called floating-point numbers store numbers that are allowed to have fractional or decimal parts. The way they represent numbers allows them to get much, much bigger, while also not being able to accurately represent every single number perfectly.

warning

The fact that floating-point numbers can’t perfectly represent all numbers in its range is important. It means there will be rounding errors and calculation errors. It is something to keep in mind when using these types–they are very different from the integer types.

Those accuracies also apply when defining super tiny numbers as well. For example, 0.00000003456.

In general, few numbers really need more than what float provides, and in game programming, most things that are not integers will be float. (In truth, decimal rarely has any practical value outside of monetary and financial calculations, where the numbers don’t get giant, but accuracy rules the day.)

Making a literal value of the double type is as simple as putting a decimal point in a number you write out:

double d = 3.14;

If you want a literal float value, you must stick an f or F on the end:

float f = 3.14f;

For a decimal literal, you stick an m or M on the end:

decimal m = 3.0m;

char an string

The char and string types are used for text. char represents a single character, though it uses two bytes and can represent any letter you’ve ever even heard of, not just English letters.

The string type is basically a sequence of char values, and can be used to represent words and sentences.

A char literal is made by using single quotes, while a string literal is formed with double quotes:

char letter = 'c';
string text = "C is for cookie.";

bool

The bool type is used to store truth values: true and false.

This might seem a little strange or useless at first glance, but truth values are an important part of programming, as we’ll see soon.

A bool is one byte in size, and literals are made by simply using the true or false keywords:

bool canHasCheezburger = true;

var

You will sometimes also see variables declared with the var type. This is a type that says, “Compiler (and humans), I think you can figure this out on your own. Please determine the type from the rest of the code around it.”

var canHasCheezburger = true;

In this case, the compiler will see that it is being assigned a value of true, so it knows that canHasCheezburger must clearly have the same type.

warning

Just because the compiler can infer the right type does not mean a human will! The var canHasCheezburger = true; example above is pretty straightforward, but it isn’t always so obvious. And if the human thinks the type is one thing, and the compiler picks something else, you’re going to have a bad time. Use var with caution.

You can only use var when the compiler can actually figure out what type you’re referring to, which is often, but not always.

tip

I recommend new programmers pass on var for the short term. Get used to the different types, and thinking about them and how they work. Types matter a lot in C#, and var tends to push the type into the shadowy corners. Start by using specific types, not var. After a while, you’ll get more comfortable with types, and can start using var when it makes sense.

danger

The var type is not a flexible type that can change over time. It still has a specific type, you just don’t write it out. It is a common misconception for new C# programmers to think of var as having a flexible type, especially if their previous experience is with programming languages whose variables don’t have fixed types.

Because var can make it harder to figure out what’s going on–especially in online, partial code snippets, missing a lot of the context–I’m going to generally avoid var on this site. If you prefer var, feel free to use it.