Skip to content
C# Programming Language Guide — .NET Development Fundamentals

C# Programming Language Guide — .NET Development Fundamentals

DodaTech Updated Jun 7, 2026 7 min read

C# is a modern, type-safe, object-oriented language from Microsoft that runs on the .NET runtime, combining the power of C++ with the simplicity of Visual Basic for building Windows, web, and cloud applications.

What You’ll Learn

  • The .NET framework and runtime
  • LINQ for querying collections
  • Async/await for asynchronous programming
  • Properties, delegates, events, and generics
  • NuGet package management

Why It Matters

C# is the primary language for the Microsoft ecosystem — Windows desktop apps with WPF/WinForms, web applications with ASP.NET, cloud services on Azure, and cross-platform apps with .NET MAUI or Unity game development. DodaZIP uses C# for its Windows shell integration and file context menu handlers. With .NET Core’s cross-platform support, C# now runs natively on Linux and macOS.

Learning Path

    flowchart LR
  A[C# Basics<br/>You are here] --> B[OOP & Properties]
  B --> C[LINQ & Delegates]
  C --> D[Async/Await]
  D --> E[Build a Web API]
  

Your First C# Program

C# programs begin in a class with a Main method. The Console class provides input/output.

using System;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello, C#!");
    }
}
dotnet new console -n HelloCSharp
cd HelloCSharp
dotnet run
# Hello, C#!

Properties and Auto-Properties

Properties encapsulate fields with get/set accessors.

using System;

class Person
{
    public string Name { get; set; }  // auto-property
    public int Age { get; private set; }  // read-only outside class

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public string Greeting => $"Hi, I'm {Name} and I'm {Age} years old.";
}

class Program
{
    static void Main()
    {
        var person = new Person("Alice", 30);
        Console.WriteLine(person.Greeting);
        // Hi, I'm Alice and I'm 30 years old.
    }
}

Delegates and Events

Delegates are type-safe function pointers. Events build on delegates for publish-subscribe patterns.

using System;

// Delegate declaration
delegate void Notify(string message);

class Publisher
{
    public event Notify OnNotify;

    public void RaiseEvent(string msg)
    {
        OnNotify?.Invoke(msg);  // null-conditional invoke
    }
}

class Program
{
    static void Handler(string msg)
    {
        Console.WriteLine($"Received: {msg}");
    }

    static void Main()
    {
        var pub = new Publisher();
        pub.OnNotify += Handler;
        pub.RaiseEvent("Hello from C# events!");
        // Received: Hello from C# events!
    }
}

LINQ — Language Integrated Query

LINQ lets you query collections using SQL-like syntax or method chains.

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        // Query syntax
        var evenNumbers = from n in numbers
                          where n % 2 == 0
                          select n * n;

        Console.WriteLine(string.Join(", ", evenNumbers));
        // 4, 16, 36, 64, 100

        // Method syntax
        var result = numbers
            .Where(n => n > 5)
            .OrderByDescending(n => n)
            .Select(n => n * 10);

        Console.WriteLine(string.Join(", ", result));
        // 100, 90, 80, 70, 60
    }
}

Async and Await

Async/await provides clean asynchronous programming without callback hell.

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var content = await FetchUrlAsync("https://example.com");
        Console.WriteLine($"Received {content.Length} characters");
    }

    static async Task<string> FetchUrlAsync(string url)
    {
        using var client = new HttpClient();
        var result = await client.GetStringAsync(url);
        return result;
    }
}

Generics

Generics create type-safe, reusable code without boxing or casting.

using System;
using System.Collections.Generic;

class Repository<T>
{
    private List<T> items = new List<T>();

    public void Add(T item) => items.Add(item);
    public T Get(int index) => items[index];
    public int Count => items.Count;
}

class Program
{
    static void Main()
    {
        var intRepo = new Repository<int>();
        intRepo.Add(10);
        intRepo.Add(20);
        Console.WriteLine(intRepo.Get(1));  // 20

        var stringRepo = new Repository<string>();
        stringRepo.Add("Hello");
        stringRepo.Add("World");
        Console.WriteLine(stringRepo.Get(0));  // Hello
    }
}

NuGet Package Manager

NuGet is the .NET package manager. It integrates with the .NET CLI:

dotnet add package Newtonsoft.Json
# Adding package 'Newtonsoft.Json' to project
using System;
using Newtonsoft.Json;

class Program
{
    static void Main()
    {
        var data = new { Name = "Alice", Age = 30 };
        string json = JsonConvert.SerializeObject(data);
        Console.WriteLine(json);
        // {"Name":"Alice","Age":30}

        var deserialized = JsonConvert.DeserializeAnonymousType(
            json, new { Name = "", Age = 0 }
        );
        Console.WriteLine(deserialized.Name);  // Alice
    }
}

Common Mistakes

1. Confusing == with .Equals() for strings

Both work for strings in C# (unlike Java) because == is overridden for string. But for custom classes, == checks reference equality unless overridden.

2. Forgetting await in async methods

var result = FetchUrlAsync(url);  // returns Task, not the result!
var result = await FetchUrlAsync(url);  // correct

3. Using var when type is unclear

var is fine when the type is obvious (var x = new List<int>()). Avoid it when it obscures readability (var x = GetData()).

4. Not disposing of IDisposable resources

Use using statements to ensure file handles, database connections, and network streams are properly closed.

5. Boxing value types unnecessarily

int x = 42;
object o = x;  // boxing — allocates on heap

Use generics to avoid boxing in collections.

6. NullReferenceException with uninitialized objects

Check for null with the ?. (null-conditional) and ?? (null-coalescing) operators.

Practice Questions

  1. What is the difference between class and struct in C#? A class is a reference type (allocated on heap, passed by reference). A struct is a value type (allocated on stack, copied on assignment).

  2. What does LINQ stand for? Language Integrated Query. It provides query capabilities directly in C# syntax.

  3. What is the purpose of async and await? They simplify asynchronous programming by letting you write async code that looks synchronous. The compiler handles the complexity of continuations.

  4. What is NuGet? The package manager for .NET. It hosts hundreds of thousands of libraries and integrates with Visual Studio and the .NET CLI.

  5. How does garbage collection work in .NET? The GC automatically reclaims memory for unreferenced objects. It uses generational collection — short-lived objects (Gen 0) are collected frequently; long-lived objects (Gen 2) less so.

Challenge: Write a C# console application that reads a CSV file, parses it into objects using LINQ, and outputs summary statistics.

Mini Project — Task Manager with Async Logging

Build a simple task manager that processes tasks in parallel with async logging.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

class TaskManager
{
    private readonly string logFile;

    public TaskManager(string logFile)
    {
        this.logFile = logFile;
    }

    private async Task LogAsync(string message)
    {
        using var writer = new StreamWriter(logFile, append: true);
        await writer.WriteLineAsync($"[{DateTime.Now:T}] {message}");
    }

    public async Task ProcessTasksAsync(IEnumerable<string> tasks)
    {
        var taskList = new List<Task>();

        foreach (var task in tasks)
        {
            taskList.Add(ProcessOneAsync(task));
        }

        await Task.WhenAll(taskList);
        await LogAsync("All tasks completed");
    }

    private async Task ProcessOneAsync(string taskName)
    {
        await LogAsync($"Starting: {taskName}");
        await Task.Delay(1000);  // simulate work
        await LogAsync($"Completed: {taskName}");
    }
}

class Program
{
    static async Task Main()
    {
        var manager = new TaskManager("tasks.log");
        var tasks = new[] { "Scan files", "Compress archive", "Send report" };
        await manager.ProcessTasksAsync(tasks);
        Console.WriteLine("Done. Check tasks.log for details.");
    }
}

FAQ

What is .NET?
.NET is a free, cross-platform runtime for C# and other languages. It includes a JIT compiler, garbage collector, base class library, and tools. .NET Core (now .NET 5+) runs on Windows, Linux, and macOS.
How is C# different from Java?
Both are C-family, GC-backed languages. C# has more features: properties, events, LINQ, async/await built in, nullable reference types, and records. Java prioritizes backward compatibility and has a larger enterprise ecosystem.
What is ASP.NET?
A web framework for building web apps, APIs, and real-time services with C#. ASP.NET Core is the modern cross-platform version.
Can I use C# with Unity?
Yes — Unity uses C# as its primary scripting language. Most Unity developers write game logic in C#.
How do I handle JSON in C#?
Use System.Text.Json (built-in) or Newtonsoft.Json (NuGet package). Both serialize/deserialize between C# objects and JSON.
What is the difference between Python and C#?
Python is dynamically typed and interpreted; C# is statically typed and compiled. C# offers better performance and tooling for large codebases, while Python provides faster prototyping.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro