Skip to Content
Course content

176: The typeof and sizeof Operators

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're managing a massive warehouse. Sometimes, you don't care about a specific box on a shelf; you just need the blueprint for that kind of box so you know how to handle it. Other times, you need to know the exact physical dimensions of a single brick so you can figure out how many of them will fit into a shipping container without wasting a single millimeter of space.

In C#, typeof is your blueprint request, and sizeof is your measuring tape.

Getting the Blueprint with typeof

When you use typeof, you're asking the runtime for the System.Type object associated with a class, struct, or interface. The key thing to remember here is that typeof happens at compile time. You aren't asking an object "What are you?"; you're asking the language "What is the definition of this type?"

public class PlayerProfile 
{ 
    public string Username { get; set; } 
}

// I don't need an actual PlayerProfile object to do this.
Type profileType = typeof(PlayerProfile);
Console.WriteLine($"The full name of the type is: {profileType.FullName}");

You'll see this a lot when you're working with reflection or dependency injection containers. I've spent plenty of hours debugging code where someone used .GetType() (which requires an instance) when they actually just needed typeof(). If you have the class name but no object, typeof is your only move.

Measuring the Footprint with sizeof

Now, sizeof is a bit more specialized. It tells you exactly how many bytes a value type occupies in memory. For most of your daily work in C#, you won't need this. But if you're doing high-performance graphics, network packet manipulation, or interfacing with C++ libraries, knowing the byte size is non-negotiable.

int intSize = sizeof(int);     // 4 bytes
long longSize = sizeof(long);    // 8 bytes
bool boolSize = sizeof(bool);    // 1 byte

Here is the catch: sizeof works out of the box for primitive types. However, if you try to use it on a custom struct, the compiler will scream at you. To get the size of a custom struct, you have to wrap the code in an unsafe block and mark your project to allow unsafe code. This is because the compiler can't always guarantee the size of a managed type due to potential alignment or padding issues.

public struct Vector3 
{ 
    public float X, Y, Z; 
}

// This requires the 'unsafe' keyword and project settings enabled
unsafe 
{ 
    int vectorSize = sizeof(Vector3); 
    Console.WriteLine($"A Vector3 takes up {vectorSize} bytes."); // 12 bytes
}

I usually advise staying away from unsafe unless you have a very specific performance reason to be there. It's powerful, but you're essentially telling the .NET runtime, "Step aside, I know what I'm doing with the memory," which is a dangerous place to be if you're not 100% sure.




📋 Practical Task

Build a Memory Footprint Analyzer

Create a small console application that analyzes the memory requirements for a hypothetical game's coordinate system. Your program should:

  • Define a struct called GameCoordinate containing two double values (X and Y) and one int (Z).
  • Use typeof to print the assembly-qualified name of the GameCoordinate struct.
  • Use sizeof (within an unsafe block) to calculate and print the total byte size of a single GameCoordinate.
  • Calculate and print how many GameCoordinate structs could theoretically fit into a 1KB (1024 bytes) buffer.

Note: Remember to add <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to your .csproj file to make the sizeof operator work with your custom struct.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.