C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
176: The typeof and sizeof Operators
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
GameCoordinatecontaining twodoublevalues (X and Y) and oneint(Z). - Use
typeofto print the assembly-qualified name of theGameCoordinatestruct. - Use
sizeof(within anunsafeblock) to calculate and print the total byte size of a singleGameCoordinate. - Calculate and print how many
GameCoordinatestructs 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.
There are no comments for now.