In today’s tech-driven world, understanding the foundations of programming is more crucial than ever. At the core of this revolution is the C# programming language, a powerful tool that has shaped everything from operating systems to embedded devices.

What makes C# so indispensable?

Its elegant simplicity and unmatched efficiency have allowed it to stand the test of time and influence countless other languages.

Welcome to our Essential Guide to C# Foundations.

This guide unravels the intricacies of C# and shows how mastering its core principles can enhance your coding skills. Whether you’re a novice eager to start your coding journey or an experienced developer looking to refresh your skills, this guide offers valuable insights and practical tips.

Let’s dive right in!

What is C# Programming Language?

C# (pronounced “C-sharp”) is a versatile and powerful programming language developed by Microsoft. It’s designed to be simple, modern, and object-oriented, making it accessible for beginners while offering advanced features for experienced developers.

For Beginners: C# is a great starting point because it has a clear and readable syntax, which means the code looks more like plain English. It’s used to build various applications, from desktop software to web apps and games. If you’re new to programming, you’ll appreciate how C# helps you understand fundamental concepts like variables, loops, conditions, and functions.

For Intermediate Developers: As you gain more experience, you’ll find that C# supports object-oriented programming (OOP), which helps you organize and manage your code better. You’ll learn about classes, objects, inheritance, and polymorphism, which are key concepts in OOP. C# also integrates well with the .NET framework, providing a vast library of pre-built code that can save you time and effort.

For Advanced Developers: C# offers advanced features like asynchronous programming, which allows you to write more efficient and responsive applications. It also supports modern programming paradigms such as LINQ (Language Integrated Query) for data manipulation and functional programming techniques. With C#, you can develop high-performance applications and take advantage of the latest advancements in software development.

Overall, C# is a robust and flexible language that grows with you as you advance in your programming journey. Whether you’re building simple applications or complex systems, C# provides the tools and features you need to succeed.

What is .NET Framework?

Source

The .NET Framework is a comprehensive software development platform created by Microsoft. It provides a consistent environment for building, deploying, and running applications on Windows.

Here are some key points to understand it better:

  • Framework Class Library (FCL): A vast collection of reusable classes, interfaces, and value types that provide a wide range of functionalities, from file reading and writing to graphic rendering and database interaction.
  • Common Language Runtime (CLR): The execution engine of the .NET Framework, which handles running applications. It provides essential services such as memory management, security, and exception handling.
  • Multi-language Support: The .NET Framework supports multiple programming languages, including C#, VB.NET, and F#. This allows developers to choose the language they are most comfortable with.
  • Interoperability: It allows for easy integration with other systems and technologies, making it versatile for various types of applications.
  • ASP.NET: A part of the .NET Framework used for building dynamic web applications and services.
  • Windows Forms and WPF: Libraries for building rich desktop applications with graphical user interfaces.
  • Security: Built-in security features help protect applications from unauthorized access and other security threats.
  • Scalability and Performance: Designed to handle large-scale applications with high performance and scalability.

What is CLR?

The Common Language Runtime (CLR) is a core component of the .NET framework. Think of it as the engine that runs .NET applications.

When you write a C# program, the magic begins with the .NET framework, which compiles your code into Intermediate Language (IL). Think of IL as a universal language that your program speaks, making it ready to travel to any machine.

Now, when you want to run your program on a different machine, you bring along this compiled IL code. But there’s a catch – this machine needs to have the Common Language Runtime (CLR) installed.

The CLR is like a master translator, taking your IL code and converting it into byte code that the machine can understand and execute. This clever process is known as Just-In-Time (JIT) compilation.

The beauty of this system is its flexibility. Your code isn’t tied down to a single operating system or architecture. Instead, it can adapt and run smoothly across various environments, making your C# programs incredibly versatile and powerful.

Here are the important points to remember:

  1. Execution Environment: The CLR provides a managed execution environment for .NET programs. This means it handles the execution of your code, ensuring it runs smoothly and efficiently.
  2. Just-In-Time Compilation (JIT): When you write .NET code, it’s initially compiled into an intermediate language (IL). The CLR then converts this IL into machine code that your computer’s processor can execute, just in time for it to run.
  3. Memory Management: One of the key features of the CLR is automatic memory management. It includes a garbage collector that automatically releases no longer-needed memory, preventing memory leaks and other common programming errors.
  4. Security: The CLR enforces security policies, ensuring that code runs in a safe and controlled manner. This helps protect your system from malicious code.
  5. Cross-Language Integration: The CLR allows code written in different .NET languages (like C#, VB.NET, and F#) to work together seamlessly. This is possible because all .NET languages are compiled into the same intermediate language.

Classes, Namespaces, and Assemblies.

When you’re diving into C# programming, you’ll encounter three fundamental components: classesnamespaces, and assemblies.

Let’s explore each one with a friendly analogy.

Classes: The Blueprint of Your Program.

Imagine you’re building a house. A class in C# is like the blueprint for that house. It defines the structure and behavior of the objects you create.

For example, if you’re creating a program to manage a library, you might have a Book class that outlines what a book is (its title, author, etc.) and what it can do (like being borrowed or returned).

Namespaces: The Organizational Tool.

Now, think of namespaces as the folders in your computer. They help you organize your classes and other types into a neat, hierarchical structure. This way, you can avoid naming conflicts and keep your code tidy.

For instance, you might have a namespace called LibraryManagement that contains all the classes related to your library program, like BookMember, and Loan.

Assemblies: The Building Blocks.

Finally, assemblies are like the completed buildings in a city. An assembly is a compiled code library used for deployment, versioning, and security. It can be an executable (.exe) or a dynamic link library (.dll).

Assemblies contain the compiled code of your classes and namespaces, making them the building blocks of your application. When you run your program, the CLR loads these assemblies to execute your code.

By understanding these components, you’ll have a solid foundation to build and organize your C# programs effectively.

.EXE vs .DLL

You can compile your C# programs as .exe or .dll files. Both types of files serve different purposes and most of the time you’ll use both file types in the real world.

Let’s understand what .exe and .dll files are and their key differences.

.exe (Executable)

  • Purpose: An .exe file is an executable file, meaning it’s a program that you can run directly. When you double-click a .exe file, it launches an application.
  • Standalone: It usually contains all the necessary code and resources to run the program independently.
  • Entry Point: An .exe file has an entry point, which is the starting point of the program (usually the Main method in a Program class).
  • Example: Think of a .exe file as a complete, ready-to-use application like a word processor or a game.
  • Purpose: A .dll file is a library that contains code and data that multiple programs can use. It cannot be run on its own.
  • Reusable: It provides functionality other programs can call upon, promoting code reuse and modularity.
  • No Entry Point: Unlike a .exe, a .dll does not have an entry point. It’s designed to be used by other applications rather than executed directly.
  • Example: A .dll file is a toolkit or plugin that adds specific features to various applications, like a spell checker that can be used by different word processors.

Key Differences

  • Execution: .exe files are standalone applications that you can run, while .dll files are libraries used by other applications.
  • Independence: .exe files can operate independently, whereas .dll files depend on other programs to be useful.
  • Purpose: .exe files are designed to perform a specific task or set of tasks, while .dll files provide reusable code and resources for multiple applications.

Your First C# Program.

Creating your first console application in C# is a great way to get started with programming.

I’ll walk through the steps to create a simple “Hello, World!” application. I’ll also explain some key parts of a C# program to help you understand the basics.

I’ll use .NET CLI to create a project to keep the process simple and avoid installing any special tools like IDE. If you prefer you can install Visual Studio and create a console project.

Step 1: Install .NET SDK (if not already installed)

Before using .NET CLI, ensure you have the .NET SDK installed.

  1. Open a terminal or command prompt.
  2. Run the following command to check if .NET is installed:

If you see a version number, the SDK is installed. If not, download and install it from Microsoft’s official site.

Here’s the .NET SDK version installed on my machine.

Step 2: Create a New Console Application.

Navigate to the directory where you want to create the project:

Run the following command to create a new console application:

  • dotnet new console → Creates a new console application.
  • -n MyConsoleApp → Specifies the project name (MyConsoleApp).

Move into the project folder:

Step 3: Explore the Project Structure

After creating the project, check the directory:

You’ll see:

  • MyConsoleApp.csproj → The project file.
  • Program.cs → The main file containing the default C# code.

Step 4: Run the Application

Execute the following command to run your app:

By default, it will print:

Hello, World!

Step 5: Modify the Code.

Open Program.cs in a text editor (e.g., VS Code). If you haven’t already installed the VS Code, you can download it from this link.

Modify the code:

Save the file and run the app again:

Step 6: Build the Application

To compile the project into an executable:

This generates the compiled files inside the bin/Debug/netX.X/ directory. Where X.X is the version of your .NET.

Step 7: Publish the Application

To create a self-contained executable:

Replace win-x64 with:

  • linux-x64 for Linux
  • osx-x64 for macOS

The output will be in the bin/Release/netX.X/win-x64/ folder.

Step 8: Run the Published Executable

Navigate to the publish folder and run the application:

This is the basic process of creating, running, and publishing a .NET Console Application using .NET CLI.

Every .NET CLI command has useful options. I would recommend bookmarking .NET CLI docs URL. This will help you find relevant commands based on your situation.

For example, you can publish your application to a specific folder using option -o.

Variables and Constants in C#.

In C#, variables and constants are used to store data. Understanding these concepts is fundamental for writing efficient programs.

Let’s break it down step by step.

Step 1: Understanding Variables

A variable is a named storage location in memory that can hold different values during the program’s execution.

How to declare a variable?

In C#, variables must be declared before use. The basic syntax is:

= ;

Example: Declaring and Using Variables.

Variable Naming Rules:

  • Must begin with a letter or an underscore (_).
  • Cannot use reserved keywords (e.g., int, class, static). To use a reserved word, prepend @ symbol, for example, @int is valid variable name.
  • Should follow camelCase naming convention (e.g., userAge, totalScore).
  • Can not start with number.
  • Can not use in between space. For example, variable name first name is invalid, and firstName is valid.

Step 2: Variable Types in C#

C# has different types of variables:

Data Type Description Example
int Stores whole numbers int age = 30;
double Stores decimal numbers double price = 99.99;
char Stores a single character char grade = 'A';
string Stores text string name = "Alice";
bool Stores true/false values bool isAdult = true;

Step 3: Constants in C#

A constant is a variable whose value cannot change once assigned.

Declaring a Constant

const = ;

Example: Using Constants.

Key Differences Between Variables and Constants.

  • Variables can change, but constants cannot.
  • Constants must be assigned a value at the time of declaration.
  • Constants are useful for fixed values like Pi, MaxUsers, etc.

Step 4: Understanding Readonly Variables

Besides const, we also have readonly variables, which are assigned a value only once, typically inside the constructor.

Example: Using readonly

Difference Between <strong>const</strong> and <strong>readonly</strong>

Feature const readonly
Can be assigned in constructor? ❌ No ✅ Yes
Value changes after assignment? ❌ No ❌ No
When assigned? At declaration In constructor
Can hold non-primitive types? ❌ No (only simple values) ✅ Yes (can store objects, arrays, etc.)

We need readonly variables in C# because constants (const) can only be assigned at compile time, while readonly variables can be assigned at runtime (typically in a constructor).

  • Use const for values that are truly fixed and known at compile time (e.g., Pi = 3.14).
  • Use readonly when a value needs to be assigned at runtime but should not change later (e.g., config values, object references, or IDs).

Step 5: Overflowing in C#

In C#, every data type has a fixed range. Overflowing occurs when a value exceeds the maximum or minimum limit of its assigned data type.

Example of Overflowing

Checked and Unchecked Blocks

C# provides checked and unchecked blocks to handle overflows explicitly.

Using unchecked, we can allow overflow without errors:

Use checked when you want to catch overflows and unchecked when performance is more important than strict range checking.

Step 6: Scope of Variables in C#

Scope refers to where a variable can be accessed in the code. There are different scopes in C#:

1. Local Scope

Variables declared inside a method or block are local and only accessible within that block.

2. Global Scope (Class-Level Variables)

Variables declared inside a class but outside methods can be accessed anywhere inside the class.

3. Block Scope

A variable declared inside {} only exists within those curly braces.

Step 7: Best Practices for Using Variables and Constants

Use meaningful names (userAge instead of x).
Prefer <strong>const</strong> when values never change.
Use <strong>readonly</strong> for values that are set once but not at compile-time.
Choose the appropriate data type (use int for whole numbers, double for decimals, etc.).
Be mindful of variable scope to avoid unintended access issues.
Use <strong>checked</strong> for critical calculations where overflow must be avoided.

By mastering variables, constants, overflowing, and scope, you can write cleaner, more efficient, and maintainable C# code! 🚀

Type Conversions in C#.

Type conversion (or type casting) in C# is the process of converting one data type into another. This is necessary when you need to store or process values in a different format.

C# provides several ways to perform type conversion, and choosing the right one depends on whether the conversion is safe, whether it might cause data loss, and whether it could fail at runtime.

There are two main types of conversions:

Implicit Conversion (Safe Conversion).

Implicit conversion happens automatically when converting from a smaller data type to a larger one, as there’s no risk of losing data.

This is done by the compiler, so no explicit action is needed.

For example:

Why does this work?

  • An int (4 bytes) can fit into a double (8 bytes) without losing any precision.
  • No risk of data loss, so the compiler allows this conversion without additional syntax.

Common implicit conversions:

  • int → long
  • float → double
  • char → int
  • byte → int

Implicit conversion does not work for:

  • double → int (decimal part could be lost)
  • long → int (if the number is too large for an int)

Explicit Conversion (Casting)

Explicit conversion is required when there’s a possibility of data loss or when converting from a larger type to a smaller type.

This is done using casting. For example:

Why use explicit conversion?

  • It tells the compiler you acknowledge possible data loss and accept it.
  • Without casting, the compiler throws an error to prevent unintended precision loss.

Common explicit conversions:

  • double → int
  • long → int
  • float → int

Caution: Casting can lead to unexpected results:

Since a byte can only store values from 0 to 255, 300 overflows and wraps around.

Using Convert Class.

C# provides the Convert class to handle conversions safely.

If the string contains non-numeric characters, it will cause an error.

Using Parse and TryParse

  • Parse: Converts a string but throws an error if the value is invalid.
  • TryParse: Returns true if conversion is successful; otherwise, false.

Boxing and Unboxing

  • Boxing: Converting a value type (e.g., int) to an object.
  • Unboxing: Extracting the value type back from the object.

Key Takeaways.

Conversion Type Example Notes
Implicit Conversion int → double Safe, no data loss
Explicit Conversion double → int Needs casting, may lose data
Convert Class Convert.ToInt32("123") Safe but can throw exceptions
Parse/TryParse int.Parse("123") / int.TryParse("ABC", out _) Parse throws an error if invalid, TryParse is safer
Boxing & Unboxing int → object Used when working with objects

Operators in C#.

Operators in C# are special symbols that perform operations on variables and values. C# provides various types of operators, including arithmetic, comparison, logical, bitwise, assignment, and more. Understanding these operators is fundamental to writing efficient and expressive C# code.

Arithmetic Operators

Arithmetic operators perform mathematical operations on numeric values. For example:

These operators are commonly used in mathematical expressions and calculations.

Operator Description Example
+ Addition a + b
- Subtraction a - b
* Multiplication a * b
/ Division a / b
% Modulus a % b

Assignment Operators

Assignment operators assign values to variables. For example:

These operators help in writing concise code.

Operator Description Example
= Assign a = b
+= Add & Assign a += b
-= Subtract & Assign a -= b
*= Multiply & Assign a *= b
/= Divide & Assign a /= b
%= Modulus & Assign a %= b

Comparison Operators

Comparison operators compare two values and return a boolean (true or false). For example:

These operators are commonly used in decision-making constructs.

Operator Description Example
== Equal to a == b
!= Not equal to a != b
> Greater than a > b
< Less than a < b
>= Greater than or equal a >= b
<= Less than or equal a <= b

Logical Operators

Logical operators are used to perform logical operations, often in conditional statements. For example:

These operators help in forming complex conditions.

Operator Description Example
&& Logical AND a && b
|| Logical OR a || b
! Logical NOT !a

Bitwise Operators

Bitwise operators perform bit-level operations on integer types. For example:

These operators are useful in low-level programming and optimizations.

Operator Description Example
& Bitwise AND a & b
| Bitwise OR a | b
^ Bitwise XOR a ^ b
~ Bitwise Complement ~a
<< Left Shift a << b
>> Right Shift a >> b

Unary Operators

Unary operators operate on a single operand.

Operator Description Example
+ Unary plus +a
- Unary minus -a
++ Increment a++ or ++a
-- Decrement a-- or --a
! Logical NOT !a

Ternary Operator

The ternary operator (? :) is a shorthand for if-else conditions.

Syntax:

Example:

Null-Coalescing Operators

These operators handle null values efficiently. For example:

The null-coalescing assignment operator (??=) can be used to assign a value only if the left-hand operand is null:

Operator Description Example
?? Returns left operand if not null, else right a ?? b
??= Assigns right operand if left is null a ??= b

These operators handle null values efficiently.

Type Conversion Operators

Type conversion operators allow explicit or implicit type conversion.

Operator Description Example
(type) Explicit Conversion (int) 3.14
as Safe Type Casting obj as string
is Type Checking obj is string

Operator Overloading

C# allows user-defined types to overload operators.

Example:

This enables expressions like:

By understanding and using these operators effectively, you can write cleaner and more efficient C# programs.