Every executable C# program needs an entry method (Main) inside a type defined within a namespace.
using System;
namespace HelloWorldApp
{
class Program
{
static void Main(string[] args) // entry point
{
Console.WriteLine("Hello World"); // prints line
}
}
}
Omit the { }
braces by placing namespace Name;
on the first line.
namespace HelloWorldApp;
class Program
{
static void Main()
=> Console.WriteLine("Hi again!");
}
using
Brings a namespace into scope for the current file.
using System.Text;
using System.Collections.Generic;
using MyDict = System.Collections.Generic.Dictionary<string,int>;
Place global using
at the top of any .cs file (or in a dedicated GlobalUsings.cs
) to include the namespace in every compilation unit.
global using System.IO;
bool, byte, sbyte, short, ushort, int, uint, long, ulong, char, float, double, decimal
int age = 30;
double salary = 1_000_000.00; // underscores for readability
var name = "Kea"; // implicit typing
decimal? bonus = null; // nullable value‑type
(char ascii, int code) pair = ('A', 65); // tuple
#nullable enable
string? middleName = null;
string firstName = "Nandi";
int[] scores = { 90, 85, 99 };
Span<int> slice = scores.AsSpan(1,2);
+, −, *, /, %, +=, -=
etc.
bool both = a && b; // short‑circuit AND
int mask = 0b_1010 | 0b_0101; // bitwise OR
string caption = userInput ?? "default"; // ?? operator
result = condition ? value1 : value2; // ?: operator
if(score >= 50) { … } else { … }
switch(dayOfWeek)
{
case DayOfWeek.Monday:
…
break;
default:
break;
}
return e switch
{
FileNotFoundException => "Missing file",
IOException io => $"I/O error ({io.Message})",
_ => "Unknown"
};
for(int i = 0; i < 10; i++) { … }
foreach(var item in collection) { … }
while(condition) { … }
do { … } while(condition);
static int Add(int x, int y) => x + y; // expression‑bodied
void Log(string message, bool urgent = false)
{
if(urgent) Console.Error.WriteLine(message);
else Console.WriteLine(message);
}
params
& Named Argumentsint Sum(params int[] nums) => nums.Sum();
var total = Sum(2,3,5,7);
Print(page:1, copies:3); // named arguments
double Hypot(double a, double b)
{
static double Squared(double v) => v * v; // static local func
return Math.Sqrt(Squared(a) + Squared(b));
}
class Person
{
public string Name { get; init; } // init‑only
public int Age { get; set; }
public Person(string name, int age)
=> (Name, Age) = (name, age);
}
base
class Employee : Person
{
public decimal Salary { get; set; }
public Employee(string n,int a,decimal s) : base(n,a)
=> Salary = s;
}
public record struct Point(int X, int Y); // value‑based
public record PersonRec(string First,string Last); // reference record
interface ILogger
{
void Log(string msg);
void LogWarning(string msg) => Log("[WARN] " + msg); // default impl
}
abstract class Shape
{
public abstract double Area();
}
public struct Vector2
{
public double X, Y;
public double Magnitude => Math.Sqrt(X*X + Y*Y);
}
[Flags]
public enum FileAccess
{
Read = 1, Write = 2, Execute = 4,
ReadWrite = Read | Write
}
delegate int Transformer(int x);
Transformer square = static x => x * x;
event EventHandler? Completed;
Completed?.Invoke(this, EventArgs.Empty);
var odds = Enumerable.Range(1,20)
.Where(n => n % 2 == 1)
.Select(n => new { n, sq = n*n });
class Stack<T>
{
readonly List<T> _items = new();
public void Push(T item) => _items.Add(item);
public T Pop() => _items[^1];
}
T Parse<T>(string s) where T : IParsable<T>
=> T.Parse(s, null);
try / catch / finally
try
{
using var file = File.OpenRead(path);
…
}
catch(IOException ex) when(ex.HResult == 32) // filter
{
…
}
finally { Console.WriteLine("Done"); }
using
Declaration (C# 8)using var conn = new SqlConnection(cs); // disposed automatically
public async Task<string> FetchAsync(Uri url,
CancellationToken ct = default)
{
using HttpClient client = new();
return await client.GetStringAsync(url, ct);
}
async
Mainstatic async Task Main()
{
var json = await FetchAsync(new("https://api.github.com"));
}
static string Grade(int mark) => mark switch
{
>= 75 and <= 100 => "Distinction",
>= 50 => "Pass",
_ => "Fail"
};
if(nums is [1, 2, .. var rest])
Console.WriteLine($"Starts with 1 2, remainder: {string.Join(',',rest)}");
[Obsolete("Use NewMethod instead")]
void OldMethod() { … }
var obsolete = typeof(Foo).GetMethod("OldMethod")!
.GetCustomAttribute<ObsoleteAttribute>();
#define DEBUG
#if DEBUG
Console.WriteLine("Debug info");
#endif
#pragma warning disable CS0168
#region legacy code
…
#endregion
unsafe
{
int value = 42;
int* p = &value;
Console.WriteLine(*p); // 42
}
Note: Requires the /unsafe
compiler flag.
This reference covers C# 1 → 12 (stable as of .NET 8, Nov 2024). Preview features for C# 13 (.NET 9) include params collections
, named lambdas, dynamic interceptor attributes, and interleave
loops. Consult the official language design notes for up‑to‑date details.