Skip to main content

C# Data Types

Data types are one of those things you deal with constantly in C#, whether you're consciously thinking about them or not. Every single variable you create is tied to a specific type, and that type dictates exactly what kind of data it's allowed to hold. 

It's a bit like sorting containers in a kitchen — you wouldn't pour soup into a box meant for dry cereal, and in the same way, you wouldn't try to stuff a block of text into a variable meant for whole numbers. Let's go through the fundamentals and get a clear picture of how this all works.

So What Is a Data Type, Really?

Put simply, a data type defines what kind of value a variable is allowed to store. C# splits these into two broad categories — value types and reference types — and understanding the difference between them tells you a lot about how your data actually behaves in memory.

Value Types vs. Reference Types

Value types hold their data directly. When you assign one value-type variable to another, C# makes a full, independent copy of that value — the two variables have nothing to do with each other after that point. int, float, and bool are all classic examples.

Reference types, on the other hand, don't hold the actual data themselves — they hold a reference pointing to where that data lives in memory. So when you assign one reference-type variable to another, you're copying the reference, not the data itself, which means both variables end up pointing at the exact same underlying object. string, arrays, and custom objects all fall into this category.

Here's a side-by-side example that makes the difference pretty obvious:

int a = 10; // Value type
int b = a;  // b is now 10, independent of a
a = 20;     // changing 'a' does not change 'b'
Console.WriteLine(b); // Outputs: 10

string str1 = "Hello"; // Reference type
string str2 = str1;    // str2 references the same string object as str1
str1 = "Goodbye";      // changing 'str1' does not change 'str2'
Console.WriteLine(str2); // Outputs: Hello

Interesting note here — even though string is technically a reference type, it behaves a bit like a value type in this example because strings in C# are immutable. Reassigning str1 doesn't modify the original string object; it points str1 at a brand-new one entirely, leaving str2 untouched.

The Value Types You'll Use Constantly

Whole Numbers

  • int — the default choice for whole numbers, covering roughly -2.1 billion to 2.1 billion.
  • short — a smaller-range integer, useful when memory is tight, going from -32,768 to 32,767.
  • long — for when you need numbers bigger than int can handle, stretching into the quintillions.

Decimal Numbers

  • float — single-precision, 32-bit floating point.
  • double — double-precision, 64-bit floating point, and generally the more common default when you need decimals.

True/False Values

  • bool — holds nothing but true or false, which makes it the natural fit for conditions and branching logic.

Putting a few of these together:

int age = 30;
float temperature = 98.6f;
bool isRaining = false;

Console.WriteLine($"Age: {age}, Temperature: {temperature}, Is it raining? {isRaining}");

The Reference Types You'll Run Into Most Often

Strings

string is what you'll reach for anytime you're dealing with text. One quirk worth knowing: strings are immutable in C#, meaning once a string object is created, it can't actually be changed in place — any "modification" is really creating a new string behind the scenes.

Arrays

Arrays let you hold a bunch of values of the same type together in one structure. They're especially handy when you're working with a known, fixed-size list of data — a set of scores, a batch of names, that kind of thing.

Objects

C# also lets you define your own classes, and any instance of a class is a reference type. Objects can bundle together all sorts of data and behavior, which makes them the backbone of most real-world C# applications.

Here's all three in action:

string greeting = "Hello, World!";
string[] colors = { "Red", "Green", "Blue" };
var person = new { Name = "John", Age = 30 }; // Anonymous object

Console.WriteLine(greeting);
foreach (var color in colors)
{
    Console.WriteLine(color);
}
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

Handling "No Value" with Nullable Types

Sometimes a variable genuinely doesn't have a value yet — think of an empty box rather than one holding a zero or an empty string. That's exactly the scenario nullable types are built for. A nullable type can hold every value its underlying type normally would, plus one extra possibility: null. You mark a type as nullable just by tacking a question mark onto the end of it.

int? optionalValue = null;

if (optionalValue.HasValue)
{
    Console.WriteLine(optionalValue.Value);
}
else
{
    Console.WriteLine("Value is null");
}

This comes up a lot more than you'd expect — anywhere a value might legitimately be "unknown" or "not yet set," rather than just zero.

Converting Between Types

At some point you'll need to move data from one type to another, and C# handles this in two different ways.

Implicit conversion happens automatically, and only when C# is confident it can make the conversion without losing any data — like converting an int to a double, since every whole number fits cleanly into a decimal type.

Explicit conversion, also called casting, is what you use when you're going the other direction — squeezing a larger or more precise type into a smaller one. This one comes with a real risk: you can lose data in the process, since the compiler can't guarantee everything will fit.

double pi = 3.14;
int wholePi = (int)pi; // Explicit conversion

Console.WriteLine(wholePi); // Outputs: 3

Notice how casting 3.14 down to an int just chops off the decimal portion entirely — that .14 is gone for good, which is exactly the kind of data loss explicit conversions can introduce if you're not careful.

Popular posts from this blog

How to Check if Someone is Connected to Your Machine in Linux

Picture this: you glance at your system monitor and notice your CPU is humming along even though you're not running anything demanding. Or maybe your internet feels sluggish for no obvious reason. A small, uneasy thought creeps in — is someone else on my machine right now? For Linux users, this isn't something you have to wonder about. Linux ships with a powerful set of built-in tools that let you see exactly who's connected, who's logged in, and what your network is doing at any given moment. You don't need to be a security expert to use them — you just need to know where to look. This guide walks you through the practical, no-nonsense steps to check for unauthorized connections on your Linux system, with real commands you can run right now. Why Monitoring Network Connections Matters Every device on a network — including your own Linux machine — communicates using an IP address. When another device or user connects to your system, that connection shows up as a trac...

How to Set Up a Linux Web Server and Host an HTML Page Easily

Setting up a web server on Linux means spending a fair amount of time in the terminal — Linux leans heavily on the command line rather than clicking through menus, so you'll be typing out instructions more often than not.  If you're new to this, it can feel a little intimidating at first, but the good news is you don't need to become a Linux wizard overnight. A handful of core commands will get you surprisingly far. A few you'll lean on constantly: cd — move between directories ls — see what's in the current directory mkdir — create a new folder nano or vim — edit files right there in the terminal sudo — run something with administrator privileges Get comfortable with these and you'll be able to navigate around, tweak configuration files, and install software without much trouble. You don't need to memorize everything — you just need to be confident enough to follow along with clear instructions, which is exactly what this guide aims to give you....

Linux Network Troubleshooting

If you've spent any time as a sysadmin — or honestly, just as someone who's had to fix their own home network at 11pm — you know that connectivity issues are one of the most common headaches out there. The good news is that a handful of core tools and a methodical approach can take you from "why isn't this working" to a root cause pretty quickly.  This guide walks through the essentials: configuring interfaces, managing routes, and diagnosing problems when things go sideways. Configuring Network Interfaces Your network interfaces are the actual bridge between your machine and the outside world, so getting them configured correctly is step one for any kind of reliable connectivity. Doing It Manually ifconfig is the old-school, tried-and-true tool for this on Unix-like systems. To see everything currently configured, run: ifconfig -a If you need to manually set up a specific interface — assigning an IP, a netmask, and bringing it online — it looks like this: ifconf...