Skip to main content

C# Reserved Keywords

Level: Beginner to Intermediate
Goal: Know what C# keywords do and when to use them - reference guide.

Keywords are words C# has reserved. You cannot use them as variable names.

Examples:

int class = 5; // ERROR: class is a keyword
int student = 5; // OK: student is not a keyword

This article catalogues all 79 keywords.


When You'll Use This in SMS

SMS code uses keywords throughout:

public class Student { }
public interface IRepository { }
public abstract class BaseEntity { }

int age = 25;
string name = "Sahasra";
bool isActive = true;

public static class Constants { }
private readonly string _id;
protected virtual void Process() { }

foreach (var student in students)
{
if (student.IsActive)
switch (student.ClassName) { case "10th": break; }
}

await ProcessStudentsAsync();

if (obj is Student student)
Console.WriteLine(student.Name);

ℹ️ Video Tutorial

C# keywords explained: all 79 categorized, escaping with @, real SMS usage. Video coming soon. Subscribe to NexCoding YouTube for updates.


ℹ️ What You'll Learn
  • All 79 C# reserved keywords organized by category
  • Type keywords (bool, int, string, void, dynamic)
  • Declaration keywords (class, interface, enum, record)
  • Access modifiers (public, private, protected, internal)
  • Modifier keywords (static, readonly, const, abstract, virtual, sealed)
  • Control flow keywords (if, for, foreach, while, switch, try, catch)
  • Object keywords (new, this, base, null, typeof, nameof)
  • Type checking keywords (is, as)
  • Parameter modifiers (ref, out, in, params)
  • Async keywords (async, await)
  • LINQ query keywords
  • Contextual keywords (var, yield, get, set)
  • When to use @ to escape keywords

C# has 79 reserved keywords - identifiers the compiler treats specially. You cannot use them as variable names unless prefixed with @. This article is a complete reference.

Type Keywords

bool // true/false - System.Boolean
byte // 0-255 - System.Byte
sbyte // -128-127 - System.SByte
char // Unicode - System.Char
short // -32768 to 32767 - System.Int16
ushort // 0-65535 - System.UInt16
int // -2B to 2B - System.Int32
uint // 0-4B - System.UInt32
long // large int - System.Int64
ulong // large uint - System.UInt64
float // 7 digits - System.Single
double // 15-17 digits - System.Double
decimal // 28-29 digits - System.Decimal (use for money)
string // text - System.String
object // base of all types - System.Object
void // no return value
dynamic // type resolved at runtime

Declaration Keywords

class // reference type blueprint
struct // value type blueprint
interface // contract with no implementation
enum // named integer constants
record // immutable reference type (C# 9+)
delegate // type-safe method reference
event // delegate-based notification

namespace // group related types
using // import namespace / resource management

// Examples
public class Student { }
public struct Point { }
public interface IGradable { }
public enum Grade { A, B, C, D, F }
public record ExamResult(int Marks, string Subject);
public delegate void NotifyHandler(string msg);

Access Modifier Keywords

public // accessible everywhere
private // same class only
protected // same class + derived classes
internal // same assembly (project)

// Combined
protected internal // same assembly OR derived
private protected // same assembly AND derived (C# 7.2)

Modifier Keywords

static // belongs to type, not instance
readonly // set once (in constructor or initializer)
const // compile-time constant
abstract // must be overridden in derived class
virtual // can be overridden
override // overrides virtual/abstract member
sealed // prevents further inheritance/override
new // hides base class member (or creates object)
partial // split class/method across files
extern // implemented outside C# (P/Invoke)
volatile // field accessed by multiple threads - no optimization
unsafe // unsafe context for pointers

Control Flow Keywords

if / else // conditional branching
switch / case / default // multi-branch on value
for // count-based loop
foreach / in // iterate collection
while // condition-based loop
do // executes at least once
break // exit loop/switch
continue // skip to next iteration
return // exit method, return value
goto // jump to label (avoid)

// Examples
for (int i = 0; i < 10; i++) { }
foreach (var s in students) { }
while (condition) { }
do { } while (condition);

Exception Handling Keywords

try // block to monitor for exceptions
catch // handle exception
finally // always executes
throw // raise exception

// Example
try
{
var student = students.First(s => s.Id == id);
}
catch (InvalidOperationException ex)
{
throw new StudentNotFoundException(id);
}
finally
{
Console.WriteLine("Search complete.");
}

Object Keywords

new // create object instance
this // reference current instance
base // reference base class
null // no reference / no value
true / false // boolean literals
typeof // get Type object at compile time
sizeof // get size of value type in bytes (unsafe context)
nameof // get name of symbol as string
default // default value of type
// typeof - get Type at compile time
Type t = typeof(Student);
Console.WriteLine(t.Name); // "Student"

// nameof - refactor-safe string
public void SetName(string name)
{
ArgumentNullException.ThrowIfNull(name, nameof(name));
// "name" string literal updates automatically if param renamed
}

// default - default value
int zero = default; // 0
string empty = default; // null
bool falsy = default; // false
Student none = default; // null

// sizeof - in unsafe context
unsafe
{
Console.WriteLine(sizeof(int)); // 4 bytes
Console.WriteLine(sizeof(double)); // 8 bytes
Console.WriteLine(sizeof(char)); // 2 bytes
}

Type Checking Keywords

is // check type / pattern match
as // safe cast - returns null if fails
// is - type check + pattern variable
object member = new Student { Name = "Sahasra", Percentage = 87.5 };

if (member is Student student)
Console.WriteLine($"Student: {student.Name}");

if (member is Student { Percentage: >= 90 }) // property pattern
Console.WriteLine("Top student");

// as - safe cast
Student? s = member as Student; // null if not Student
if (s != null)
Console.WriteLine(s.Name);

// vs hard cast - throws InvalidCastException if fails
var s2 = (Student)member; // throws if wrong type

Checked / Unchecked - Overflow Control

// Default - overflow silently wraps around (unchecked)
int max = int.MaxValue; // 2147483647
int wrapped = max + 1; // -2147483648 (silent overflow!)

// checked - throws OverflowException
try
{
int result = checked(max + 1);
}
catch (OverflowException)
{
Console.WriteLine("Overflow detected!");
}

// checked block
checked
{
int marks = int.MaxValue;
int bonus = marks + 1; // throws OverflowException
}

// unchecked - explicit, suppress overflow check
unchecked
{
int wrapped2 = int.MaxValue + 1; // -2147483648, no exception
}

// School Management use case - total marks calculation
static int SafeTotalMarks(int[] marks)
{
int total = 0;
checked // catch any overflow in marks calculation
{
foreach (int m in marks)
total += m;
}
return total;
}

Parameter Modifier Keywords

ref // pass by reference - caller's variable modified
out // output parameter - method MUST assign
in // read-only reference - no copy, no modification
params // variable number of arguments

// Examples
static void Swap(ref int a, ref int b) { int t = a; a = b; b = t; }
static bool TryParse(string s, out int result) { /* ... */ }
static double GetPercentageFast(in ExamResult r) { /* read only */ }
static int Total(params int[] marks) => marks.Sum();

Async Keywords

async // marks method as asynchronous
await // suspends until Task completes

// Example
async Task<Student> GetStudentAsync(int id)
{
await Task.Delay(100);
return new Student { Id = id, Name = "Sahasra" };
}

Query (LINQ) Keywords

// Used in query syntax
from // data source
where // filter
select // projection
group // grouping
into // continuation
orderby // sorting
join // join collections
let // intermediate variable
on / equals / by // join clauses

// Example
var result =
from s in students
where s.Percentage >= 75
orderby s.Percentage descending
select new { s.Name, s.Percentage };

Contextual Keywords (Not Reserved - Special in Context)

// These are NOT reserved - can use as identifiers but have special meaning in context
var // type inference
dynamic // dynamic type
yield // iterator (yield return, yield break)
value // in property setter
get / set / init // property accessors
add / remove // event accessors
where // generic constraints
when // catch filter + pattern matching
record // immutable type (C# 9+)
required // required property (C# 11+)
file // file-scoped access modifier (C# 11+)
scoped // lifetime scope for ref structs

Escape Reserved Keywords with @

💻 Try It — Console App
💡 Paste into Program.cs and press F5⌥ GitHub
// If you MUST use a keyword as identifier (legacy code, DB columns)
string @class = "10th"; // @ escapes the reserved keyword
int @readonly = 100;
var @event = "Annual Day";

Console.WriteLine(@class); // "10th"

Complete Keyword Count by Category

CategoryKeywords
Types16
Declaration8
Access Modifiers6
Modifiers12
Control Flow11
Exception4
Object10
Type Checking2
Overflow2
Parameter Modifiers4
Async2
LINQ Query14
Total~79

Common Mistakes

? Trying to use keyword as variable name:

int class = 10; // ERROR - class is reserved
string @event = ""; // OK - but bad style

? Use clear names instead of escaping:

int studentClass = 10; // Clear intent
string eventName = ""; // Better than @event

? Confusing abstract, virtual, override:

public class Student
{
public virtual string GetGrade() => "A"; // Can be overridden
public abstract void Calculate(); // Error - method has body
}

? Correct usage:

public abstract class Person
{
public virtual string GetGrade() => "A"; // Can override, has implementation
public abstract string GetName(); // Must override, no implementation
}

public class Student : Person
{
public override string GetName() => "Sahasra";
public override string GetGrade() => "A+";
}

? Using const for values that change:

public const decimal LateFeeRate = 0.01m; // Can't change at runtime!

// Later in code:
LateFeeRate = 0.02m; // Error - const is immutable

? Use readonly for runtime values:

public static readonly decimal LateFeeRate = 0.01m; // Can be set once

// In static constructor:
static Config()
{
LateFeeRate = decimal.Parse(configFile); // OK
}

? Forgetting @ when legacy DB column matches keyword:

public class Student
{
public string class { get; set; } // Error - class is keyword
}

? Use @ to escape:

public class Student
{
[Column("class")]
public string @class { get; set; } // OK, maps to "class" column
}

? Not understanding sealed (can't inherit):

public sealed class Final { }

public class Derived : Final { } // Error - sealed class can't be inherited

? Sealed prevents inheritance:

public class Derived : Student { } // OK - Student not sealed

// Override in sealed prevents further override
public sealed override string GetGrade() => "A+"; // No subclass can override

Best Practices

  1. Know the keywords in your domain - Understand types, modifiers you use most
  2. Prefer not escaping keywords - Use clear names instead of @keyword
  3. Use abstract for interfaces needing code - Default to interfaces, use abstract only if shared code needed
  4. Mark virtual only if subclass override expected - Don't mark methods virtual by default
  5. Use readonly over const for runtime values - More flexible
  6. Prefer is pattern matching over as - More modern, safer
  7. Use nameof() instead of string literals - Refactor-safe parameter names
  8. Mark classes sealed if no subclassing needed - Signals intent, allows optimizations
  9. Understand modifier combinations - protected internal (OR), private protected (AND)
  10. Use params for optional argument lists - More readable than arrays
  11. Document why checked/unchecked needed - Overflow is rare, document when it matters
  12. Know contextual vs reserved - var not reserved, can use as name (but don't)

🎯 Q1: What's the difference between abstract, virtual, and override?

abstract: Method has NO implementation. Derived class MUST override. Used in abstract classes/interfaces.

virtual: Method HAS implementation. Derived class CAN override. Optional.

override: Used in derived class to override virtual/abstract.

public abstract class Person
{
public abstract string GetName(); // No body, must override
public virtual string GetEmail() => ""; // Has default, can override
}

public class Student : Person
{
public override string GetName() => "Sahasra"; // Must override
public override string GetEmail() => "Sahasra@x.com"; // Optional override
}

Abstract = mandatory, virtual = optional.

🎯 Q2: Const vs readonly - when use each?

const: Compile-time constant. Value baked into code. Can't change ever.

readonly: Runtime constant. Set once (constructor or initializer). More flexible.

public const double PI = 3.14159; // Compile-time, never changes
public readonly int StudentId; // Set in constructor, then fixed

public Student(int id)
{
StudentId = id; // Set once here
}

PI = 3.1; // Error
StudentId = 100; // Error

Use const for mathematical constants. Use readonly for values computed/configured at runtime.

🎯 Q3: What does sealed keyword do?

sealed class: Can't be inherited. End of inheritance chain.

sealed override: Subclass can't further override this method.

public sealed class Final { }
public class Derived : Final { } // ERROR - sealed

public class Base
{
public virtual void Work() { }
}

public class Derived : Base
{
public sealed override void Work() { } // Can override once
}

public class Further : Derived
{
public override void Work() { } // ERROR - sealed
}

Sealed prevents inheritance, signals "don't subclass", allows JIT optimizations.

🎯 Q4: How are abstract class and interface different?

Abstract class: IS-A relationship. Can have code, state, constructors. Single inheritance.

Interface: CAN-DO capability. No code (pre-C# 8), no state. Multiple implementation.

public abstract class Animal // IS-A - an animal
{
public void Breathe() { } // Shared code
public int Age { get; set; } // State
public abstract void Move();
}

public interface ISwimmable // CAN-DO - can swim
{
void Swim(); // No implementation (pre-C# 8)
}

public class Fish : Animal, ISwimmable // One abstract, multiple interfaces
{
public override void Move() => Swim();
public void Swim() { }
}

Abstract when shared code. Interface when just contract.

🎯 Q5: What are contextual keywords?

Contextual keywords NOT reserved - can use as identifiers. But have special meaning in context.

var x = 10; // var - type inference, contextual
int yield = 5; // yield as variable OK, but yield return in iterator has special meaning

// These work:
string var = "text"; // Legal but confusing
string value = "x"; // OK - value contextual in property setter

// But in iterator - yield has special meaning:
IEnumerable<int> Count()
{
for (int i = 1; i <= 10; i++)
yield return i; // yield return - special, not regular return
}

Contextual keywords flexible but use carefully to avoid confusion.

🎯 Q6: When should I use the @ symbol to escape keywords?

Only when legacy code forces you. Don't do it otherwise.

// ? Bad - unnecessary escape
string @this = "value";

// ? Good - legacy DB column named "class"
[Column("class")]
public string @class { get; set; }

// ? Good - API contract requires "namespace"
public class ApiResponse
{
[JsonPropertyName("namespace")]
public string @namespace { get; set; }
}

Use @ only when external constraint (DB column, API field, legacy code) forces keyword usage. Otherwise rename.


🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on C# reserved keywords. Try these prompts:

  • "What is the difference between abstract, virtual, and override keywords in C#?"
  • "Explain the difference between const and readonly in C# with examples"
  • "What does the sealed keyword do in C# and when should I use it?"
  • "Quiz me on C# keywords - describe a keyword and I will name it"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Next Article

Boxing, Unboxing, Stack vs Heap ->

nexcoding.in