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
3: Anatomy of a C# Program
I once mentored a junior dev who spent nearly an entire afternoon fighting with the compiler. He had written a perfectly valid logic block to calculate shipping costs, but he'd pasted it directly into a new file without wrapping it in a class. He kept getting a barrage of errors saying the "method must have a return type" or that "identifiers cannot be declared here." He was convinced his installation of Visual Studio was corrupted. In reality, he was just trying to write a function in the "void." C# is an object-oriented language, and unlike Python or JavaScript, it is incredibly picky about where a piece of code lives. If it's not inside a class, and that class isn't inside a namespace, the compiler simply doesn't know what to do with it.
The Nested Hierarchy of C#
Think of a C# file like a set of Russian nesting dolls. You can't just throw a line of code onto the page; it has to be contained. At the outermost layer, we have the namespace. This is essentially a way to organize your code and prevent naming collisions. If you're building a massive app, you might have a Project.UI namespace and a Project.Data namespace. It keeps things tidy.
Inside that namespace, you'll find the class. In C#, almost every piece of logic you write must reside inside a class. A class is a blueprint. Whether you're defining a User, a DatabaseConnection, or just a Program to run some logic, the class provides the necessary structure for the runtime to manage your code.
using System;
namespace GearCalculatorApp
{
class GearLogic
{
// Logic goes here
}
}
Notice that using System; at the top? That's a directive. It tells C#, "Hey, I'm going to be using tools from the System library (like the Console), so don't make me type System.Console.WriteLine every single time." It's a quality-of-life shortcut we use in almost every single file.
The Gateway: The Main Method
You can have a hundred classes in your project, but the computer needs to know exactly where to start. This is the role of the Main method. It is the official entry point of your application. When you hit "Run," the .NET runtime searches for a method called Main inside a class. If it can't find one, your program won't start.
I'll show you a complete example of a simple gear ratio calculator. Pay attention to how the method is tucked inside the class, and the class is tucked inside the namespace.
using System;
namespace GearCalculatorApp
{
class Program
{
static void Main(string[] args)
{
double driveGear = 12;
double drivenGear = 36;
double ratio = drivenGear / driveGear;
Console.WriteLine("The gear ratio is: " + ratio);
}
}
}
The static void Main(string[] args) line looks like a mouthful, but it's a standard pattern. static means the runtime can call this method without having to create an "instance" of the Program class first. void means the method does its job and finishes without returning a value back to the operating system. The string[] args part allows your program to accept inputs from the command line, though you won't need that for most of our early exercises.
Managing Scope with Curly Braces
If there is one thing that trips up beginners, it's the curly braces {}. In C#, these define the boundaries, or "scope," of your code. Everything between the opening brace of the namespace and its closing brace belongs to that namespace. The same goes for classes and methods.
A common mistake is accidentally closing a brace too early. If you close your class brace before your method is finished, the compiler will get confused and tell you that your method is "outside of a class." I always recommend using an IDE's auto-indentation feature; if your code suddenly shifts to the left unexpectedly, you've probably misplaced a brace. Keep your nesting clean, and the compiler will be much kinder to you.
📋 Practical Task
Fixing the Broken GearRatio Calculator
The following code was written by a developer who forgot the "nesting dolls" rule. The program is intended to calculate a gear ratio, but it will not compile because the Main method is floating outside of a class, and the using directive is misplaced.
Your Task: Rewrite the code so that the Main method is properly wrapped inside a class named Program, and that class is wrapped inside a namespace called GearApp. Ensure the using System; directive is at the very top.
class Program
{
// This is empty!
}
static void Main(string[] args)
{
double drive = 10;
double driven = 40;
Console.WriteLine("Ratio: " + (driven / drive));
}
using System;There are no comments for now.